Convert LDAP Date in SQL (milliseconds to nanoseconds)

时光怂恿深爱的人放手 提交于 2019-12-11 11:43:36

问题


I am getting date in milliseconds format.

i.e.: 1427342400000 is essentially 3/26/2015.

Now I want to further convert date in nanoseconds and pass this value in accountexpires attribute in Active Directory.

What is the query to convert milliseconds date to nanoseconds date?

Any help would be greatly appreciated.


回答1:


Now I want to further convert date in nanoseconds

Ok, but convert to nano seconds since when? Looking at your example, I assume the start point to be '01-JAN-1970'.

If I want to convert a date to milliseconds since 01-JAN-1970, I would do this:

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

        MILLISECONDS
--------------------
       1424428022000

SQL>

Now,

1 millisecond = 1000000 nanosecond

, using this formula, just multiply it to the difference of the date.

Convert a date to nanoseconds:

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>

To convert it back to date:

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>

UPDATE Regarding the TIMEZONE

It is better to explicitly mention the timezone.

You could mention the timezone in the literal itself, or cast it as UTC and convert it to your local timezone.

Please see this answer.




回答2:


When you say "1427342400000 is essentially 3/26/2015", it looks like a Unix timestamp.

According my findings the LDAP timestamp is

The number of 100-nanoseconds intervals since 1601-01-01 00:00:00 UTC.

And a Unix timestamp is

The number of seconds (sometimes milliseconds are used) since 1970-01-01 00:00:00 UTC.

I assume you get a Unix timestamp and you want to convert to a LDAP timestamp. This function should work:

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

Update:

You can to it much sorter:

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

However, you get a difference of 5160 seconds (86 Minutes) but I don't have any idea why you get this. For an interval between 2 dates the time zone should have no influence.



来源:https://stackoverflow.com/questions/28620762/convert-ldap-date-in-sql-milliseconds-to-nanoseconds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!