【问题标题】:Convert LDAP Date in SQL (milliseconds to nanoseconds)在 SQL 中转换 LDAP 日期(毫秒到纳秒)
【发布时间】:2015-04-21 15:31:34
【问题描述】:

我正在获取milliseconds 格式的日期。

即:1427342400000 is essentially 3/26/2015

现在我想进一步转换nanoseconds 中的日期,并将此值传递给 Active Directory 中的 accountexpires 属性。

将毫秒日期转换为纳秒日期的查询是什么?

任何帮助将不胜感激。

【问题讨论】:

    标签: sql oracle oracle11g date-arithmetic


    【解决方案1】:

    现在我想进一步以纳秒为单位转换日期

    好的,但是从什么时候开始转换为纳秒?看你的例子,我假设起点是'01-JAN-1970'

    如果我想将日期转换为毫秒,因为01-JAN-1970,我会这样做:

    SQL> SELECT to_number(SYSDATE - to_date('01-JAN-1970','DD-MON-YYYY')) * (24 * 60 * 60 * 1000) milliseconds
      2  FROM dual;
    
            MILLISECONDS
    --------------------
           1424428022000
    
    SQL>
    

    现在,

    1 毫秒 = 1000000 纳秒

    ,使用这个公式,只需乘以日期的差

    将日期转换为纳秒:

    SQL> SELECT to_number(SYSDATE - to_date('01-JAN-1970','DD-MON-YYYY')) * (24 * 60 * 60 * 1000 * 1000000) nanoseconds
      2  FROM dual;
    
             NANOSECONDS
    --------------------
     1424428111000000000
    
    SQL>
    

    要将其转换回日期:

    SQL> alter session set nls_date_format='DD-MON-YYYY HH24:MI:SS';
    
    Session altered.
    
    SQL> SELECT TO_CHAR(to_date('1970-01-01 00','yyyy-mm-dd hh24')
      2         +
      3        (1424428111000000000 )/1000000/1000/60/60/24 , 'YYYY-MM-DD HH12:MI:SS am') nano_to_date
      4  FROM dual;
    
    NANO_TO_DATE
    ----------------------
    2015-02-20 10:28:31 am
    
    SQL>
    

    更新关于TIMEZONE

    最好明确提及时区。

    您可以在文字本身中提及时区,或将其转换为 UTC 并将其转换为您的 local timezone

    请看这个answer

    【讨论】:

    • 考虑 Unix 纪元是 1970:01:01 00:00:00 UTC!它可能与您当地的时区不同。
    • 是的,同意。 OP只是想知道将日期转换为纳秒,所以我没有太注意添加时区。我已经在这里stackoverflow.com/a/26711372/3989608 回答了类似的问题。无论如何,我将编辑我的答案并添加此链接
    【解决方案2】:

    当您说“1427342400000 本质上是 2015 年 3 月 26 日”时,它看起来像一个 Unix 时间戳。

    根据我的发现,LDAP 时间戳是

    1601-01-01 00:00:00 UTC 以来的 100 纳秒间隔数。

    而 Unix 时间戳是

    1970-01-01 00:00:00 UTC 以来的秒数(有时使用毫秒)。

    我假设您获得了 Unix 时间戳,并且您想要转换为 LDAP 时间戳。 这个功能应该可以工作:

    CREATE OR REPLACE FUNCTION ConvertTime(unixTimestamp IN NUMBER) RETURN NUMBER IS
        timestampUTC TIMESTAMP;
        theInterval INTERVAL DAY(9) TO SECOND(9);
        epoche NUMBER;
    BEGIN
    
        -- Convert Unix Timestamp-Number to TIMESTAMP:
        timestampUTC := (TIMESTAMP '1970-01-01 00:00:00' AT TIME ZONE 'UTC' + unixTimestamp * (INTERVAL '1' SECOND / 1000));
    
        -- Convert TIMESTAMP to LDAP Timestamp-Number 
        theInterval := timestampUTC - TIMESTAMP '1601-01-01 00:00:00' AT TIME ZONE 'UTC';
        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 * 1e9/100);
    
    END ConvertTime;
    
    
    SELECT TO_CHAR(ConvertTime(1427342400000), 'fm999999999999999999999') FROM dual;
    
    130718108400000000
    

    更新:

    你可以给它多分拣:

    SELECT 
        TO_CHAR((1427342400000/1000 + (DATE '1970-01-01' - DATE '1601-01-01')*24*60*60) * (1e9/100), 'fm999999999999999999999') AS LDAP_TS
    FROM dual;
    
    130718160000000000
    

    但是,您会得到 5160 秒(86 分钟)的差异,但我不知道您为什么会这样。对于两个日期之间的间隔,时区应该没有影响。

    【讨论】:

      猜你喜欢
      • 2011-05-17
      • 2014-10-12
      • 2013-10-31
      • 2015-11-14
      • 2016-07-16
      • 2017-10-17
      • 2017-10-29
      • 2019-12-24
      • 1970-01-01
      相关资源
      最近更新 更多