This question already has answers here:
Convert from date to epoch-Oracle
(3 answers)
Closed 10 months ago.
Does anyone have a better AND faster solution on getting the unix epoch timestamp using Oracle SQL than this?:
SQL> select (cast(sysdate as date) - cast(to_date('1970-01-01', 'YYYY-MM-DD') as date)) * 86400 as unixepoch from dual;
UNIXEPOCH
----------
1490789604;
Oneliner preferred ;)
The above answer is only correct if your database time zone is in UTC. Unix time is always in UTC.
The correct answer that works on any database, regardless of configuration is:
--Convert current time to epoch.
select (cast (systimestamp at time zone 'UTC' as date) - date '1970-01-01') * 86400
from dual
--Convert hard-coded timestamp to epoch.
select (cast (timestamp '2019-12-31 23:59:59' at time zone 'UTC' as date) - date '1970-01-01') * 86400
from dual;
You do not need to cast the values as dates, since they are already dates.
SELECT ( SYSDATE - DATE '1970-01-01' ) * 86400 AS unixepoch
FROM DUAL;
Related
I am using a H2 Database where i need to convert the Epoch to Datetime (24 hours) format. I have the below sample detail.
TABLE: MTTR
COLUMN : END_TIME
VALUE : 1659946913581
I have the below query ,
select
to_char((DATEADD('SECOND', ((END_TIME/ 1000) + 19800), DATE '1970-01-01')), 'yyyy-mm-dd hh:mi:ss') AS END_TIME_VAL
from MTTR;
The issue is that it is giving the incorrect value as '2022-08-08 01:51:53'. It should be '2022-08-08 13:51:53'. What changes can be done here ?
If you expect 2022-08-08 13:51:53, your time zone has +05 offset from UTC, so you can use something like
-- This command isn't needed if your connection already has the proper time zone
SET TIME ZONE '+05';
SELECT END_TIME * INTERVAL '0.001' SECOND + TIMESTAMP '1970-01-01 05:00:00' FROM MTTR;
in all recent versions of H2 database.
While trying to convert datetime to epoch, I am getting an error: ORA-01810: format code appears twice
QracleSQL query:
select (trunc(TO_TIMESTAMP('2022-05-08T19:09:17Z', 'yyyy-MM-dd"T"HH:mm:ssXXX')) - TO_DATE('01/01/1970', 'MM/DD/YYYY')) * 24 * 60 * 60 from dual;
You should use:
TO_TIMESTAMP_TZ instead of TO_TIMESTAMP
the format model YYYY-MM-DD"T"HH24:MI:SS.FF TZD rather than incorrectly using MM twice, HH24 instead of HH, .FF instead of XXX, and TZD instead of hardcoding "Z".
Make sure you always convert your timestamp to UTC time zone (yours is already but others may not be)
Don't TRUNCate the timestamp to a DATE at midnight or you will lose the time component.
Like this:
SELECT ROUND(
(
TRUNC(timestamp_value AT TIME ZONE 'UTC', 'MI')
- DATE '1970-01-01'
) * 86400
+ EXTRACT(SECOND FROM timestamp_value AT TIME ZONE 'UTC')
) AS epoch_time
FROM (
SELECT TO_TIMESTAMP_TZ(
'2022-05-08T19:09:17Z',
'YYYY-MM-DD"T"HH24:MI:SS.FF TZD'
) AS timestamp_value
FROM DUAL
);
Which outputs:
EPOCH_TIME
1652033357
db<>fiddle here
Something like this:
TEST DATA
create table sample_inputs (ts_string) as
select '2022-05-08T16:49:34Z' from dual union all
select '2022-04-15T04:20:13.525Z' from dual
;
QUERY AND OUTPUT
with
prep (ts_string, ts) as (
select ts_string,
to_timestamp(ts_string, 'yyyy-mm-dd"T"hh24:mi:ss.ff"Z"')
from sample_inputs
)
select ts_string,
round((trunc(ts, 'mi') - date '1970-01-01') * 24 * 3600)
+ extract(second from ts)
as epoch
from prep;
TS_STRING EPOCH
-------------------------- -----------
2022-05-08T16:49:34Z 1652028574
2022-04-15T04:20:13.525Z 1649996413.525
NOTES
In your attempt there are several mistakes. The Oracle fractional-seconds element is ff, not xxx. You are missing the placeholder for the hard-coded Z at the end (you have "T" in your mask, which is correct, but you are missing the similar "Z"). HH is insufficient - it must be either HH24 or HH followed by AM (or equivalently PM) at the end. In your example, it is obviously HH24. And MM and mm mean the same thing in Oracle - this is not Unix. The element for minutes is mi or equivalently MI.
The query I wrote preserves fractional seconds in the epoch. Another question earlier today (perhaps yours too, under another user name) was closed as being a "duplicate" - but the claimed "duplicate" has absolutely nothing about preserving fractional seconds, when the input is an Oracle timestamp vs an Oracle date (which always does have a time component, but only in whole seconds).
I have input date as a column in table "22/03/2022 06:59:59"
I need to convert into EPOCH time -
Expected output- "1647932399" timezone(jakarta, Indonesia)
reference link- https://www.epochconverter.com/
time zone of input data is - UTC +7:00(Jakarta)
Tried with this-SQL CODE
SELECT (CAST(SYS_EXTRACT_UTC(to_timestamp('22/03/2022 06:59:59','dd/mm/yyyy HH:MI:SS' )) AS DATE) - TO_DATE('01/01/1970','DD/MM/YYYY')) * 24 * 60 * 60 FROM DUAL;
Result displayed is 1647907199
But didn't get the expected output
1647932399 is the epoch for 2022-03-22 06:59:59 UTC. Your start time is 22-03-22 06:59:59 Asia/Jakarta, which is 22-03-21 23:59:59 UTC, and the epoch for that is 1647907199 - which is what you're getting. So your result is correct; but risky.
You are relying on implicit conversion.
to_timestamp('22/03/2022 06:59:59','dd/mm/yyyy HH:MI:SS') gives you a plain timestamp, with no time zone information. When you then do SYS_EXTRACT_UTC(...) the plain timestamp is implicitly converted to a timestamp with time zone using your session time zone - which happens to be Jakarta, it seems. So it works - for you, in this session. If you change your session time zone, or more likely if someone else runs the same code from a session with a different time zone, then the reslut will be different.
To be more explicit, you can convert your string to a plain timestamp, then declare that it represents a Jakarta time, and then convert that to UTC:
sys_extract_utc(from_tz(to_timestamp('22/03/2022 06:59:59', 'DD/MM/YYYY HH24:MI:SS'), 'Asia/Jakarta'))
21-MAR-22 23.59.59.000000000 UTC
There are then basically two ways to convert that to an epoch number; either cast it to a date, subtract 1970-01-01 as a date, and manipulate the resulting number of days (as in your question):
select
round(
(
cast(
sys_extract_utc(from_tz(to_timestamp('22/03/2022 06:59:59', 'DD/MM/YYYY HH24:MI:SS'), 'Asia/Jakarta'))
as date)
- date '1970-01-01'
) * 24 * 60 * 60
) as result
from dual;
1647907199
Or leave it as a timestamp, subtract 1970-01-01 as a timestamp, and manipulate the resulting interval:
select
(extract(day from diff) * 24 * 60 * 60)
+ (extract(hour from diff) * 60 * 60)
+ (extract(minute from diff) * 60)
+ extract(second from diff)
as result
from (
select sys_extract_utc(from_tz(to_timestamp('22/03/2022 06:59:59', 'DD/MM/YYYY HH24:MI:SS'), 'Asia/Jakarta'))
- timestamp '1970-01-01 00:00:00' as diff
from dual
);
1647907199
Note that either way you can easily get the short result that was the basis for your previous question, by truncating the number or extracting just the days, without explicitly subtracting the 23:59:59 part. Either gives you 19072.
db<>fiddle
I need to convert a date from a TextBox from date to epoch time so that I can insert it into Oracle DB.
I managed to convert from epoch to date as below, but couldn't find a way to convert it the other way.
SelectCommand="SELECT ID,
COMPANY,
FIRST_NAME,
LAST_NAME,
ID_NUMBER,
(SELECT TO_CHAR(TO_DATE('01-JAN-1970','DD/MM/YYYY')
+(TRAINING_DATE/60/60/24), 'MM/DD/YYYY') FROM dual) AS TRAINING_DATE,
(SELECT TO_CHAR(TO_DATE('01-JAN-1970','DD/MM/YYYY')
+(TRAINING_VALABILITY/60/60/24),'MM/DD/YYYY') FROM dual) AS TRAINING_VALABILITY
FROM CONTRACTORS
ORDER BY COMPANY"
Subtracting DATE '1970-01-01' from the value will give the number of days (and fractional hours/minutes/seconds) difference and then you can multiply by 24*60*60:
(date_value - DATE '1970-01-01')*24*60*60
Update:
Typically, epoch time is measured from 1970-01-01T00:00:00 UTC. If your date is not in UTC then you will need to convert time zones.
For example, if your date has the time zone Europe/Berlin:
( CAST(
FROM_TZ(
CAST( date_value AS TIMESTAMP ), -- Cast to timestamp
'Europe/Berlin' -- Convert to expected Time Zone
)
AT TIME ZONE 'UTC' -- Convert Time Zone to UTC
AS DATE -- Cast back to DATE data type
)
- DATE '1970-01-01'
)*24*60*60
db<>fiddle
UpdateCommand="UPDATE CONTRACTORS
SET COMPANY=:COMPANY,
FIRST_NAME=:FIRST_NAME,
LAST_NAME=:LAST_NAME,
ID_NUMBER=:ID_NUMBER,
TRAINING_DATE=(TO_DATE(:TRAINING_DATE, 'MM-DD-YYYY HH24:MI:SS') - TO_DATE('01-JAN-1970','DD/MM/YYYY'))*24*60*60,
TRAINING_VALABILITY=(TO_DATE(:TRAINING_VALABILITY, 'MM-DD-YY`enter code here`YY HH24:MI:SS') - TO_DATE('01-JAN-1970','DD/MM/YYYY'))*24*60*60
WHERE (ID=:ID)"
I use this solution which works correctly whether the input date, in local time, is during Daylight Saving Time (DST) or not.
SELECT Round((Cast(Sys_extract_utc( Cast( your_date_field AS TIMESTAMP )) AS DATE) - To_date('1970-01-01','YYYY-MM-DD HH24MISS')) *24*60*60) AS epoch FROM dual;
-- 'your_date_field'
-- '20210112' -> 1610427600 (no DST)
-- '20210512' -> 1620792000 (DST)
I need to convert a date from a TextBox from date to epoch time so that I can insert it into Oracle DB.
I managed to convert from epoch to date as below, but couldn't find a way to convert it the other way.
SelectCommand="SELECT ID,
COMPANY,
FIRST_NAME,
LAST_NAME,
ID_NUMBER,
(SELECT TO_CHAR(TO_DATE('01-JAN-1970','DD/MM/YYYY')
+(TRAINING_DATE/60/60/24), 'MM/DD/YYYY') FROM dual) AS TRAINING_DATE,
(SELECT TO_CHAR(TO_DATE('01-JAN-1970','DD/MM/YYYY')
+(TRAINING_VALABILITY/60/60/24),'MM/DD/YYYY') FROM dual) AS TRAINING_VALABILITY
FROM CONTRACTORS
ORDER BY COMPANY"
Subtracting DATE '1970-01-01' from the value will give the number of days (and fractional hours/minutes/seconds) difference and then you can multiply by 24*60*60:
(date_value - DATE '1970-01-01')*24*60*60
Update:
Typically, epoch time is measured from 1970-01-01T00:00:00 UTC. If your date is not in UTC then you will need to convert time zones.
For example, if your date has the time zone Europe/Berlin:
( CAST(
FROM_TZ(
CAST( date_value AS TIMESTAMP ), -- Cast to timestamp
'Europe/Berlin' -- Convert to expected Time Zone
)
AT TIME ZONE 'UTC' -- Convert Time Zone to UTC
AS DATE -- Cast back to DATE data type
)
- DATE '1970-01-01'
)*24*60*60
db<>fiddle
UpdateCommand="UPDATE CONTRACTORS
SET COMPANY=:COMPANY,
FIRST_NAME=:FIRST_NAME,
LAST_NAME=:LAST_NAME,
ID_NUMBER=:ID_NUMBER,
TRAINING_DATE=(TO_DATE(:TRAINING_DATE, 'MM-DD-YYYY HH24:MI:SS') - TO_DATE('01-JAN-1970','DD/MM/YYYY'))*24*60*60,
TRAINING_VALABILITY=(TO_DATE(:TRAINING_VALABILITY, 'MM-DD-YY`enter code here`YY HH24:MI:SS') - TO_DATE('01-JAN-1970','DD/MM/YYYY'))*24*60*60
WHERE (ID=:ID)"
I use this solution which works correctly whether the input date, in local time, is during Daylight Saving Time (DST) or not.
SELECT Round((Cast(Sys_extract_utc( Cast( your_date_field AS TIMESTAMP )) AS DATE) - To_date('1970-01-01','YYYY-MM-DD HH24MISS')) *24*60*60) AS epoch FROM dual;
-- 'your_date_field'
-- '20210112' -> 1610427600 (no DST)
-- '20210512' -> 1620792000 (DST)