问题
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