12

我在数据库中有一个时间戳数据类型,格式为 24-JuL-11 10.45.00.000000000 AM,并且想将其转换为 unix 时间戳,我该如何获得它?

4

10 回答 10

24

这个问题几乎是Convert Unixtime to Datetime SQL (Oracle)的反面

正如贾斯汀洞穴所说:

没有内置函数。但是写一个相对容易。因为 Unix 时间戳是自 1970 年 1 月 1 日以来的秒数

由于从另一个日期中减去一个日期会导致它们之间的天数,您可以执行以下操作:

create or replace function date_to_unix_ts( PDate in date ) return number is

   l_unix_ts number;

begin

   l_unix_ts := ( PDate - date '1970-01-01' ) * 60 * 60 * 24;
   return l_unix_ts;

end;

自 1970 年以来以为单位,小数秒数无关紧要。您仍然可以使用时间戳数据类型调用它...

SQL> select date_to_unix_ts(systimestamp) from dual;

DATE_TO_UNIX_TS(SYSTIMESTAMP)
-----------------------------
                   1345801660

针对您的评论,我很抱歉,但我没有看到这种行为:

SQL> with the_dates as (
  2    select to_date('08-mar-12 01:00:00 am', 'dd-mon-yy hh:mi:ss am') as dt
  3      from dual
  4     union all
  5    select to_date('08-mar-12', 'dd-mon-yy')
  6      from dual )
  7  select date_to_unix_ts(dt)
  8    from the_dates
  9         ;

DATE_TO_UNIX_TS(DT)
-------------------
         1331168400
         1331164800

SQL>

有 3,600 秒的差异,即 1 小时。

于 2012-08-24T08:42:28.410 回答
13

我意识到答案已被接受,但我认为应该明确该答案中的函数不考虑传入日期的时区偏移量。应在 GMT (+0) 计算正确的 Unix 时间戳。Oracle 的to_date函数假定传入的日期在本地时区,除非另有说明。夏令时是真实存在的,这一事实加剧了这个问题。我通过以下功能解决了这个问题:

create or replace
  function unix_time_from_date
      (
        in_date   in date,
        in_src_tz in varchar2 default 'America/New_York'
      )
    return integer
  as
    ut      integer       := 0;
    tz      varchar2(8)   := '';
    tz_date timestamp with time zone;
    tz_stmt varchar2(255);
  begin
    /**
     * This function is used to convert an Oracle DATE (local timezone) to a Unix timestamp (UTC).
     *
     * @author James Sumners
     * @date 01 February 2012
     *
     * @param in_date An Oracle DATE to convert. It is assumed that this date will be in the local timezone.
     * @param in_src_tz Indicates the time zone of the in_date parameter.
     *
     * @return integer
     */

    -- Get the current timezone abbreviation (stupid DST)
    tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual';
    execute immediate tz_stmt into tz_date;
    select
      extract(timezone_abbr from tz_date)
    into tz
    from dual;

    -- Get the Unix timestamp
    select
      (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400)
    into ut
    from dual;

    return ut;
end unix_time_from_date;

我有一些配套功能,unix_time并且unix_time_to_date,可在http://jrfom.com/2012/02/10/oracle-and-unix-timestamps-revisited/获得。如果不实施这些,我无法相信 Oracle 已经一路发展到 11g。

于 2012-11-02T00:25:22.353 回答
3

日期:

   FUNCTION date_to_unix (p_date  date,in_src_tz in varchar2 default 'Europe/Kiev') return number is
begin
    return  round((cast((FROM_TZ(CAST(p_date as timestamp), in_src_tz) at time zone 'GMT') as date)-TO_DATE('01.01.1970','dd.mm.yyyy'))*(24*60*60));
end;

对于时间戳:

FUNCTION timestamp_to_unix (p_time  timestamp,in_src_tz in varchar2 default 'Europe/Kiev') return number is
    begin
        return  round((cast((FROM_TZ(p_time, in_src_tz) at time zone 'GMT') as date)-TO_DATE('01.01.1970','dd.mm.yyyy'))*(24*60*60));
    end;
于 2014-04-16T13:36:22.137 回答
2

我正在使用以下方法,它与其他答案略有不同,因为它使用sessiontimezone()函数来正确获取日期

    select
    ( 
      cast((FROM_TZ(CAST(in_date as timestamp), sessiontimezone) at time zone 'GMT') as date) -- in_date cast do GMT
      - 
      TO_DATE('01.01.1970','dd.mm.yyyy') -- minus unix start date
    )
    * 86400000 -- times miliseconds in day
    from dual;
于 2017-04-25T14:26:15.557 回答
0

这就是我想出的:

select    substr(extract(day from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 24 * 60 * 60 + 
          extract(hour from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 60 * 60 + 
          extract(minute from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 60 + 
          trunc(extract(second from (n.origstamp - timestamp '1970-01-01 00:00:00')),0),0,15) TimeStamp 
          from tablename;

FWIW

于 2014-06-25T22:36:25.330 回答
0
SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00', 'DD-MM-YYYY HH24:MI:SS')) * 24 * 60 * 60 * 1000 FROM DUAL
于 2018-01-16T08:26:16.350 回答
0

对于 Oracle 时间和 Unix 时间之间的转换,我使用这些函数。他们会考虑您当前的时区。您还应该添加DETERMINISTIC关键字,例如,如果您想在基于函数的索引中使用此类函数。DATE和之间的转换TIMESTAMP应该由 Oracle 隐式完成。

FUNCTION Timestamp2UnixTime(theTimestamp IN TIMESTAMP, timezone IN VARCHAR2 DEFAULT SESSIONTIMEZONE) RETURN NUMBER DETERMINISTIC IS
    timestampUTC TIMESTAMP;
    theInterval INTERVAL DAY(9) TO SECOND;
    epoche NUMBER;
BEGIN
    timestampUTC := FROM_TZ(theTimestamp, timezone) AT TIME ZONE 'UTC';
    theInterval := TO_DSINTERVAL(timestampUTC - TIMESTAMP '1970-01-01 00:00:00');
    epoche := EXTRACT(DAY FROM theInterval)*24*60*60 
        + EXTRACT(HOUR FROM theInterval)*60*60 
        + EXTRACT(MINUTE FROM theInterval)*60 
        + EXTRACT(SECOND FROM theInterval);
    RETURN ROUND(epoche);
END Timestamp2UnixTime;



FUNCTION UnixTime2Timestamp(UnixTime IN NUMBER) RETURN TIMESTAMP DETERMINISTIC IS
BEGIN
    RETURN (TIMESTAMP '1970-01-01 00:00:00 UTC' + UnixTime * INTERVAL '1' SECOND) AT LOCAL;
END UnixTime2Timestamp;
于 2019-01-03T09:05:41.007 回答
0

我同意Wernfried DomscheitJames Sumners在他们的帖子中解释的解决方案——主要是因为时区和夏季/冬季问题!

我更喜欢更短且没有动态 SQL 的函数之一:

-- as Date 
CAST ( FROM_TZ( TIMESTAMP '1970-01-01 00:00:00' + NUMTODSINTERVAL(input_date , 'SECOND') , 'GMT' ) AT TIME ZONE 'Europe/Berlin' AS DATE )

或者

-- as Timestamp
FROM_TZ( to_timestamp(Date '1970-01-01' + input_date / 86400 ), 'GMT' ) AT TIME ZONE 'Europe/Berlin'

由于“时区”需要放置静态字符串(即“欧洲/柏林”)而不是 dbtimezone 或 sessiontimezone 变量,因为这可能会产生错误的偏移量,因为执行时间可能在 Summer 而 unix Timestamp 可能在冬天。

于 2021-06-17T13:42:54.810 回答
0

以上所有都这样做: -

ORA-01873: 区间的前导精度太小

如果您的日期是 TIMESTAMP 格式。

这是正确的答案(假设您足够聪明,可以将服务器设置为使用 UTC。)

select (cast(sys_extract_utc(current_timestamp) as date) - TO_DATE('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS')) * 86400 as gmt_epoch from dual;
于 2021-11-29T10:59:50.977 回答
-1
SELECT 
to_char(sysdate, 'YYYY/MM/DD HH24:MI:SS') dt,
round((sysdate - to_date('19700101 000000', 'YYYYMMDD HH24MISS'))*86400) as udt 
FROM dual; 
于 2015-08-05T11:57:02.370 回答