Number to Date conversion (Oracle) - oracle

I have a number that matches a date and I have no idea how the number is calculated using that date, here are three examples:
08/08/2018 12:23 73691437391180
08/08/2018 12:32 73691437976165
11/11/2015 14:41 73591349310000
If I substract the second from the first, I get the difference of 9.74975 which corresponds to the minutes (and seconds?) passed?
Thanks in advance!
PS: The data is stored in an Oracle Database. It is possible to generate more examples if needed.

Someone seems to have had some fun dreaming this up. The difference between two values does appear to be milliseconds, but they aren't obvious epoch times.
By a process of elimination it looks like a compound value, as it didn't reliably match as a single value, e.g. dividing by 60*60*24 and variants. It seems to eb based on an epoch time of 0001-01-02 00:00:00 UTC.
The first six digits seem to be the number of days since January 2nd (?) in the year 1 AD/CE. Trying a few possible epoch dates threw up:
select date '2018-08-08' - date '0001-01-01' from dual;
DATE'2018-08-08'-DATE'0001-01-01'
---------------------------------
736915
which was too close to be a coincidence, but was a day out, so it's really based on 0001-01-02, apparently.
The remaining 8 digits seem to be the number of milliseconds after midnight UTC - again just assuming it was from midnight was close, but an hour or two out. So there is also a time zone component, which perhaps make sense and matches your profile location.
This seems to work for the sample values at least:
with t (ts) as (
select timestamp '2018-08-08 11:23:11.180' from dual
union all select timestamp '2018-08-08 11:32:56.165' from dual
union all select timestamp '2015-11-11 14:41:50.000' from dual
)
select ts,
100000000 * extract(day from ts - timestamp '0001-01-02 01:00:00')
+ 3600000 * extract(hour from ts - timestamp '0001-01-02 01:00:00')
+ 60000 * extract(minute from ts - timestamp '0001-01-02 01:00:00')
+ 1000 * extract(second from ts - timestamp '0001-01-02 01:00:00') as n
from t;
N TS
-------------- -------------------------------------------
73691437391180 2018-08-08 12:23:11.180000000 EUROPE/VIENNA
73691437976165 2018-08-08 12:32:56.165000000 EUROPE/VIENNA
73591349310000 2015-11-11 14:41:50.000000000 EUROPE/VIENNA
or to convert the other way, starting from a timestamp rather than a date as there are fractional seconds and time zones involved:
with t (ts) as (
select timestamp '2018-08-08 12:23:11.180 Europe/Vienna' from dual
union all select timestamp '2018-08-08 12:32:56.165 Europe/Vienna' from dual
union all select timestamp '2015-11-11 14:41:50.000 Europe/Vienna' from dual
)
select ts,
100000000 * extract(day from ts - timestamp '0001-01-02 00:00:00 UTC')
+ 3600000 * extract(hour from ts - timestamp '0001-01-02 00:00:00 UTC')
+ 60000 * extract(minute from ts - timestamp '0001-01-02 00:00:00 UTC')
+ 1000 * extract(second from ts - timestamp '0001-01-02 00:00:00 UTC') as n
from t;
TS N
------------------------------------------- --------------
2018-08-08 12:23:11.180000000 EUROPE/VIENNA 73691437391180
2018-08-08 12:32:56.165000000 EUROPE/VIENNA 73691437976165
2015-11-11 14:41:50.000000000 EUROPE/VIENNA 73591349310000
Which is all a bit... unusual.
It's also possible, for the timestamp-to-number conversion, that the starting value is a plain timestamp; this would get the same result via implicit conversion as long as your session was in that time zone.

Related

Oracle SQL convert number (that stores a timestamp) to human readable date time on select

I have a timestamp stored on a column called ts of type NUMBER(15, 0), and I want to print their corresponding human readable datetime in any human readable format, like '2022-03-15 23:08:24'.
None of what I have tried works, but the most closed thing is:
select
to_date('19700101', 'YYYYMMDD') + ( 1 / 24 / 60 / 60 / 1000) * ts
from my_table;
But this translates ts to a human readable date, not a datetime. I'm not able to show the hours, minutes and seconds. I think Oracle SQL has functions to translate timestamps to datetimes in a straightforward way, but it requires the timestamp is stored on a TIMESTAMP column, but in my case it's a NUMBER.
You are generating a date, which retains the time to second precision, but loses the milliseconds. You're also ignoring the time zone your ts is nominally in, which is presumably UTC - as an epoch/Unix time.
Anyway, you can change how the date is displayed by changing your session settings, or with to_char():
select
to_char(
date '1970-01-01' + (1 / 24 / 60 / 60 / 1000) * ts,
'YYYY-MM-DD HH24:MI:SS'
)
from my_table;
If you want to keep milliseconds, and preserve time zone, use a timestamp and intervals instead:
select
to_char(
timestamp '1970-01-01 00:00:00 UTC' + ((ts / 1000) * interval '1' second),
'YYYY-MM-DD HH24:MI:SS.FF3 TZR'
) as string_result
from my_table;
With an example ts value of 1655977424456, that gives result 2022-06-23 09:43:44.456 UTC
The result is still UTC. You can also convert the time to a different time zone if that's useful; for example:
select
to_char(
(timestamp '1970-01-01 00:00:00 UTC' + ((ts / 1000) * interval '1' second))
at time zone 'Europe/Madrid',
'YYYY-MM-DD HH24:MI:SS.FF3'
)
from my_table;
The same example ts value of 1655977424456 now gives 2022-06-23 11:43:44.456 EUROPE/MADRID, or just 2022-06-23 11:43:44.456 if you leave the TZR off the format model or convert to a plain timestamp.
And you should only convert to a string to display - not to store or manipulate or pass around the actual timestamp value.
db<>fiddle with some variations.

checking expiryDate in Oracle query

I have a table which contains the start date, ExpiryDate, I want to write an oracle query which checks if the expiry date is greater than the current system date, Then I want to return that row, else null will be the result of the query.
I wrote something like this,
select Name,Password,StartDate,ExpiryDate from db_name where UserName = 'abc' and status =1 and ExpiryDate >=(SELECT Round((sysdate - to_date('01-JAN-1970','DD-MON-YYYY')) * (86400))*1000 as dt FROM dual);
Here is the table description:
STARTDATE NOT NULL NUMBER(20)
EXPIRYDATE NOT NULL NUMBER(20)
The values:
EXPIRYDATE
----------
1.5880E+12
after performing query like select to_char(startdate),to_char(expirydate) I am getting
TO_CHAR(STARTDATE)
----------------------------------------
TO_CHAR(EXPIRYDATE)
----------------------------------------
1587909960000
1587996480000
But it is working fine for all cases, but if the expiry date is less than( the current time+6hrs) it is giving null, can anyone tell me how to solve this?
Unix epoch time is in the UTC time zone. You can convert the current time to UTC time zone and then subtract the epoch:
SELECT Name,
Password,
StartDate,
ExpiryDate
FROM IM_USER_MANAGEMENT
WHERE UserName = 'abc'
AND status =1
AND ExpiryDate >= ( CAST( SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE )
- DATE '1970-01-01'
)*24*60*60*1000
Unix epoch time, eh? See if this helps.
Set date format to something recognizable:
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
Sample data:
SQL> select * From test;
STARTDATE EXPIRYDATE
---------------------- ----------------------
1587909960000 1587996480000
Converted to DATE values:
SQL> select
2 date '1970-01-01' + ( 1 / 24 / 60 / 60 / 1000) * startdate startdt,
3 date '1970-01-01' + ( 1 / 24 / 60 / 60 / 1000) * expirydate expdt
4 from test;
STARTDT EXPDT
------------------- -------------------
26.04.2020 14:06:00 27.04.2020 14:08:00
Or, using it along with sysdate:
SQL> select *
2 from test
3 where sysdate between
4 date '1970-01-01' + ( 1 / 24 / 60 / 60 / 1000) * startdate and
5 date '1970-01-01' + ( 1 / 24 / 60 / 60 / 1000) * expirydate;
STARTDATE EXPIRYDATE
---------------------- ----------------------
1587909960000 1587996480000
As sysdate currently is:
SQL> select sysdate from dual;
SYSDATE
-------------------
27.04.2020 12:45:56
It looks to me like these dates of yours are Javascript style timestamps. That is, it looks like they are times since the UNIX epoch 1970-01-01 00:00:00 UTC measured in milliseconds. Notice they're with reference to UTC, not your local time zone. Is your time zone Asia/Dhaka? That's the one six hours ahead of UTC.
It also looks to me like your timestamps have ten-second precision. The two you showed are divisible by 10 000.
This is the formula for converting Javascript times to Oracle UTC date/time values
SELECT TO_DATE('19700101','yyyymmdd') + (1587909960000/86400000) FROM DUAL;
This yields a SYSDATE - style rendering of your values in UTC time, not local time. It yields 2020-04-26 14:06:00
Because you have a six-hour apparent error, I guess your local time zone is Asia/Dhaka, UTC+6. But it also could possibly be America/Denver, UTC-6.
and your time value, run through that formula, yields 2020-04-26 14:06:00. Which seems like a valid recent date/time.
This is a GUESS! If you're working with other peoples' money or lives in your database, ask the person who programmed it. It's not a DBMS-native way of doing things, so you should double-check.
What's going on in the formula?
In Oracle, adding 1.0 to a SYSDATE - style value adds one calendar day to it. So we start with the Oracle date for the UNIX epoch TO_DATE('19700101','yyyymmdd').
Then we take your millisecond timestamp value and convert it to days, dividing by 86 400 000, Finally we add it to the epoch date.
Here are some suggestions about getting the current time in UTC, so you can compare it to your timestamp data. How to get UTC value for SYSDATE on Oracle

Oracle how to convert Timestamp with any Timezone, to Date with database server Timezone

I have a timestamp column, which contains data with different timezones. I need to select records which belongs to a given 'day' of database server timezone.
For example, if the data in MY_TIMESTAMP column is 19-MAR-19 00.37.56.030000000 EUROPE/PARIS.
And on given date 19-MAR-19 (also represented as 2019078) where the database server is on EUROPE/LONDON.
Is there any way so that if my database server is in EUROPE/LONDON timezone, then this record is ignored but if it is in EUROPE/PARIS, then the record is selected.
Please note that the given timestamp is first hour of the day and EUROPE/PARIS is ahead of EUROPE/LONDON by one hour
The query I tried, unfortunately ignores the timezone of timestamp.
select *
from MY_TABLE
where
to_number(to_char(CAST(MY_TIMESTAMP AS DATE), 'RRRRDDD')) between 2019078 AND 2019079
There is below mentioned way to convert TIMESTAMP from know timezone to a date in required timezone but I cannot use this logic as the source timezone is not know.
CAST((FROM_TZ(CAST(MY_TIMESTAMP AS TIMESTAMP),'EUROPE/PARIS') AT TIME ZONE 'EUROPE/LONDON') AS DATE)'
You don't need to convert the table data; as well as being more work, doing so would stop any index on that column being used.
Oracle will honour time zones when comparing values, so compare the original table data with the specific day - and convert that to a timestamp with time zone:
select *
from MY_TABLE
where MY_TIMESTAMP >= timestamp '2019-03-19 00:00:00 Europe/London'
and MY_TIMESTAMP < timestamp '2019-03-20 00:00:00 Europe/London'
or if you want to base it on today rather than a fixed date:
where MY_TIMESTAMP >= from_tz(cast(trunc(sysdate) as timestamp), 'Europe/London')
and MY_TIMESTAMP < from_tz(cast(trunc(sysdate) + 1 as timestamp), 'Europe/London')
or if you're being passed the dates as YYYYDDD values (replace fixed value with numeric argument name):
where MY_TIMESTAMP >= from_tz(to_timestamp(to_char(2019078), 'RRRRDDD'), 'Europe/London')
and MY_TIMESTAMP < from_tz(to_timestamp(to_char(2019079), 'RRRRDDD'), 'Europe/London')
Quick demo with some sample data in a CTE, in two zones for simplicity:
with my_table (id, my_timestamp) as (
select 1, timestamp '2019-03-19 00:37:56.030000000 Europe/Paris' from dual
union all
select 2, timestamp '2019-03-19 00:37:56.030000000 Europe/London' from dual
union all
select 3, timestamp '2019-03-19 01:00:00.000000000 Europe/Paris' from dual
union all
select 4, timestamp '2019-03-20 00:37:56.030000000 Europe/Paris' from dual
union all
select 5, timestamp '2019-03-20 00:37:56.030000000 Europe/London' from dual
)
select *
from MY_TABLE
where MY_TIMESTAMP >= timestamp '2019-03-19 00:00:00 Europe/London'
and MY_TIMESTAMP < timestamp '2019-03-20 00:00:00 Europe/London'
/
ID MY_TIMESTAMP
---------- --------------------------------------------------
2 2019-03-19 00:37:56.030000000 EUROPE/LONDON
3 2019-03-19 01:00:00.000000000 EUROPE/PARIS
4 2019-03-20 00:37:56.030000000 EUROPE/PARIS
The first sample row is excluded because 00:37 in Paris is still the previous day in London. The second and third are included because they are both in the early hours of that day - the third row just scrapes in. The fourth row is included for the same reason the first was excluded - 00:37 tomorrow is still today from London. And the fifth is excluded because it's after midnight in London.

Convert local datetime (with time zone) to a Unix timestamp in Oracle

I currently have a SQL query that returns the correct local DATETIME from a Unix TIMESTAMP column in our DB.
Here is an example using a specific TIMESTAMP of 1539961967000:
SELECT FROM_TZ(CAST(DATE '1970-01-01' + 1539961967000 * (1/24/60/60/1000) AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/Denver' DATETIME
FROM dual;
which returns:
DATETIME
19-OCT-18 09.12.47.000000000 AM AMERICA/DENVER
I am having a hard time reversing this query to return a Unix TIMESTAMP starting with a local DATETIME.
Has anyone ever encountered this before?
You can convert your timestamp with timezone to UTC, and then subtract the epoch from that:
select timestamp '2018-10-19 09:12:47.0 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual;
which gives you an interval data type:
DIFF
----------------------
+17823 15:12:47.000000
You can then extract the elements from that, and multiply each element by an appropriate factor to convert it to milliseconds (i.e. for days, 60*60*24*1000); and then add them together:
select extract(day from diff) * 86400000
+ extract(hour from diff) * 3600000
+ extract(minute from diff) * 60000
+ extract(second from diff) * 1000 as unixtime
from (
select timestamp '2018-10-19 09:12:47.0 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual
);
UNIXTIME
--------------------
1539961967000
db<>fiddle
This preserves milliseconds too, if the starting timestamp has them (this converts from a 'Unix' time while preserving them):
select (timestamp '1970-01-01 00:00:00.0 UTC' + (1539961967567 * interval '0.001' second))
at time zone 'America/Denver' as denver_time
from dual;
DENVER_TIME
--------------------------------------------
2018-10-19 09:12:47.567000000 AMERICA/DENVER
then to convert back:
select extract(day from diff) * 86400000
+ extract(hour from diff) * 3600000
+ extract(minute from diff) * 60000
+ extract(second from diff) * 1000 as unixtime
from (
select timestamp '2018-10-19 09:12:47.567 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual
);
UNIXTIME
--------------------
1539961967567
db<>fiddle
If your starting timestamp has greater precision than that then you'll need to truncate (or round/floor/ceil/cast) to avoid having a non-integer result; this version just truncates the extracted milliseconds part:
select diff,
extract(day from diff) * 86400000
+ extract(hour from diff) * 3600000
+ extract(minute from diff) * 60000
+ trunc(extract(second from diff) * 1000) as unixtime
from (
select timestamp '2018-10-19 09:12:47.123456789 AMERICA/DENVER'
- timestamp '1970-01-01 00:00:00.0 UTC' as diff
from dual
);
DIFF UNIXTIME
------------------------- --------------------
+17823 15:12:47.123456789 1539961967123
Without that truncation (or equivalent) you'd end up with 1539961967123.456789.
I'd forgotten about the leap seconds discrepancy; if you need/want to handle that, see this answer.
The main issue is that Oracle has two ways (at least) to convert a number of seconds to an interval day-to-second - either with a function or with a simple arithmetic operation on an interval literal - but no direct way to do the reverse.
In the two queries below, first I show how to convert a UNIX timestamp (in milliseconds since the Epoch) to an Oracle timestamp, without losing milliseconds. (See my comment under your Question, where I point out that your method will lose milliseconds.) Then I show how to reverse the process.
Like you, I ignore the difference between "timestamp at UTC" and "Unix timestamp" caused by "Unix timestamp" ignoring leap seconds. Your business must determine whether that is important.
Unix timestamp to Oracle timestamp with time zone (preserving milliseconds):
with
inputs (unix_timestamp) as (
select 1539961967186 from dual
)
select from_tz(timestamp '1970-01-01 00:00:00'
+ interval '1' second * (unix_timestamp/1000), 'UTC')
at time zone 'America/Denver' as oracle_ts_with_timezone
from inputs
;
ORACLE_TS_WITH_TIMEZONE
--------------------------------------
2018-10-19 09:12:47.186 America/Denver
Oracle timestamp with time zone to Unix timestamp (preserving milliseconds):
with
sample_data (oracle_ts_with_timezone) as (
select to_timestamp_tz('2018-10-19 09:12:47.186 America/Denver',
'yyyy-mm-dd hh24:mi:ss.ff tzr') from dual
)
select ( extract(second from ts)
+ (trunc(ts, 'mi') - date '1970-01-01') * (24 * 60 * 60)
) * 1000 as unix_timestamp
from ( select cast(oracle_ts_with_timezone at time zone 'UTC'
as timestamp) as ts
from sample_data
)
;
UNIX_TIMESTAMP
----------------
1539961967186

oracle convert unix epoch time to date

The context is that there is an existing application in our product which generates and sends the EPOCH number to an existing oracle procedure & vice versa. It works in that procedure using something like this
SELECT UTC_TO_DATE (1463533832) FROM DUAL
SELECT date_to_utc(creation_date) FROM mytable
When I tried these queries it does work for me as well with Oracle 10g server (and oracle sql developer 4.x if that matters).
In the existing procedure the requirement was to save the value as date itself (time component was irrelevant), however in the new requirement I have to convert unix EPOCH value to datetime (at the hours/mins/seconds level, or better in a specific format such as dd-MMM-yyyy hh:mm:ss) in an oracle query. Strangely I am unable to find any documentation around the UTC_TO_DATE and DATE_TO_UTC functions with Google. I have looked around at all different questions on stackoverflow, but most of them are specific to programming languages such as php, java etc.
Bottom line, how to convert EPOCH to that level of time using these functions (or any other functions) in Oracle query? Additionally are those functions I am referring could be custom or specific somewhere, as I don't see any documentation or reference to this.
To convert from milliseconds from epoch (assume epoch is Jan 1st 1970):
select to_date('19700101', 'YYYYMMDD') + ( 1 / 24 / 60 / 60 / 1000) * 1322629200000
from dual;
11/30/2011 5:00:00 AM
To convert that date back to milliseconds:
select (to_date('11/30/2011 05:00:00', 'MM/DD/YYYY HH24:MI:SS') - to_date('19700101', 'YYYYMMDD')) * 24 * 60 * 60 * 1000
from dual;
1322629200000
If its seconds instead of milliseconds, just omit the 1000 part of the equation:
select to_date('19700101', 'YYYYMMDD') + ( 1 / 24 / 60 / 60 ) * 1322629200
from dual;
select (to_date('11/30/2011 05:00:00', 'MM/DD/YYYY HH24:MI:SS') - to_date('19700101', 'YYYYMMDD')) * 24 * 60 * 60
from dual;
Hope that helps.
Another option is to use an interval type:
SELECT TO_TIMESTAMP('1970-01-01 00:00:00.0'
,'YYYY-MM-DD HH24:MI:SS.FF'
) + NUMTODSINTERVAL(1493963084212/1000, 'SECOND')
FROM dual;
It has this advantage that milliseconds won't be cut.
If your epoch time is stored as an integer.....
And you desire the conversion to Oracle date format.
Step 1-->
Add your epoch date (1462086000) to standard 01-jan-1970. 86400 is seconds in a 24 hour period.
*Select TO_DATE('01-jan-1970', 'dd-mon-yyyy') + 1462086000/86400 from dual*
**output is 5/1/2016 7:00:00 AM**
Step 2--> Convert it to a CHAR . This is needed for formatting before additional functions can be applied.
*Select TO_CHAR(TO_DATE('01-jan-1970', 'dd-mon-yyyy') + 1462086000/86400 ,'yyyy-mm-dd hh24:mi:ss') from dual*
output is 2016-05-01 07:00:00
Step 3--> Now onto Timestamp conversion
Select to_timestamp(TO_CHAR(TO_DATE('01-jan-1970', 'dd-mon-yyyy') + 1462086000/86400 ,'yyyy-mm-dd hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss') from dual
output is 5/1/2016 7:00:00.000000000 AM
Step 4--> Now need the TimeZone, usage of UTC
Select from_tz(to_timestamp(TO_CHAR(TO_DATE('01-jan-1970', 'dd-mon-yyyy') + 1462086000/86400 ,'yyyy-mm-dd hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss'),'UTC') from dual
output is 5/1/2016 7:00:00.000000000 AM +00:00
Step 5--> If your timezone need is PST
Select from_tz(to_timestamp(TO_CHAR(TO_DATE('01-jan-1970', 'dd-mon-yyyy') + 1462086000/86400 ,'yyyy-mm-dd hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss'),'UTC') at time zone 'America/Los_Angeles' TZ from dual
output is 5/1/2016 12:00:00.000000000 AM -07:00
Step 6--> Format the PST Timezone timestamp.
Select to_Char(from_tz(to_timestamp(TO_CHAR(TO_DATE('01-jan-1970', 'dd-mon-yyyy') + 1462086000/86400 ,'yyyy-mm-dd hh24:mi:ss'), 'yyyy-mm-dd hh24:mi:ss'),'UTC') at time zone 'America/Los_Angeles' ,'DD-MON-YYYY HH24:MI:SS') TZ from dual
output is 01-MAY-2016 00:00:00
Step 7--> And finally, if your column is date datatype
Add to_DATE to the whole above Select.
Here it is for both UTC/GMT and EST;
GMT select (to_date('1970-01-01 00','yyyy-mm-dd hh24') +
(1519232926891)/1000/60/60/24) from dual;
EST select new_time(to_date('1970-01-01 00','yyyy-mm-dd hh24') +
(1519232926891)/1000/60/60/24, 'GMT', 'EST') from dual;
I thought somebody would be interested in seeing an Oracle function version of this:
CREATE OR REPLACE FUNCTION unix_to_date(unix_sec NUMBER)
RETURN date
IS
ret_date DATE;
BEGIN
ret_date:=TO_DATE('19700101','YYYYMMDD')+( 1/ 24/ 60/ 60)*unix_sec;
RETURN ret_date;
END;
/
I had a bunch of records I needed dates for so I updated my table with:
update bobfirst set entered=unix_to_date(1500000000+a);
where a is a number between 1 and 10,000,000.
A shorter method to convert timestamp to nanoseconds.
SELECT (EXTRACT(DAY FROM (
SYSTIMESTAMP --Replace line with desired timestamp --Maximum value: TIMESTAMP '3871-04-29 10:39:59.999999999 UTC'
- TIMESTAMP '1970-01-01 00:00:00 UTC') * 24 * 60) * 60 + EXTRACT(SECOND FROM
SYSTIMESTAMP --Replace line with desired timestamp
)) * 1000000000 AS NANOS FROM DUAL;
NANOS
1598434427263027000
A method to convert nanoseconds to timestamp.
SELECT TIMESTAMP '1970-01-01 00:00:00 UTC' + numtodsinterval(
1598434427263027000 --Replace line with desired nanoseconds
/ 1000000000, 'SECOND') AS TIMESTAMP FROM dual;
TIMESTAMP
26/08/20 09:33:47,263027000 UTC
As expected, above methods' results are not affected by time zones.
A shorter method to convert interval to nanoseconds.
SELECT (EXTRACT(DAY FROM (
INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval --Maximum value: INTERVAL '+694444 10:39:59.999999999' DAY(6) TO SECOND(9) or up to 3871 year
) * 24 * 60) * 60 + EXTRACT(SECOND FROM (
INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval
))) * 1000000000 AS NANOS FROM DUAL;
NANOS
1598434427263027000
A method to convert nanoseconds to interval.
SELECT numtodsinterval(
1598434427263027000 --Replace line with desired nanoseconds
/ 1000000000, 'SECOND') AS INTERVAL FROM dual;
INTERVAL
+18500 09:33:47.263027
As expected, millis, micros and nanos are converted and reverted, dispite of SYSTIMESTAMP doesn't have nanosecounds information.
Replace 1000000000 by 1000, for example, if you'd like to work with milliseconds instead of nanoseconds.
I've tried some of posted methods, but almost of them are affected by the time zone or result on data loss after revertion, so I've decided do post the methods that works for me.

Resources