Matt
Matt

Reputation: 179

Oracle - Convert Unixtime to local datetime including DST (Daylight Savings Time) and vice versa

I have a NUMBER field (UTCSTAMP) with UnixTimestamps and I would like to have a (custom) function to easily return local datetime (Europe/Amsterdam) including DST (Daylight Savings Time). The output should be this format: 'yyyy-mm-dd hh24:mi:ss' For example: unix_ts2date_function(1576666800)

I found this article: Convert Unixtime to Datetime SQL (Oracle) but it doesn't take Daylight Savings Time into account.

I would also like to have a (custom) function to easily convert a local datetime (Europe/Amsterdam) including DST (Daylight Savings Time) to a UnixTimestamp and use it in a WHERE clause. For example:

SELECT * FROM table
WHERE UTCSTAMP > date2unix_ts_function('2019-05-01') (DST is active)
AND UTCSTAMP < date2unix_ts_function('2020-11-30') (DST not active)

I also found this article: Convert timestamp datatype into unix timestamp Oracle but it also doesn't take Daylight Savings Time into account.

Upvotes: 0

Views: 904

Answers (2)

MT0
MT0

Reputation: 168406

Add a utcstamp seconds to the epoch 1970-01-01 UTC (as a TIMESTAMP data type) and then use AT TIME ZONE to convert it to your desired time zone:

Oracle Setup:

CREATE TABLE your_table ( utcstamp ) AS
SELECT 1576666800 FROM DUAL

Query:

SELECT ( TIMESTAMP '1970-01-01 00:00:00 UTC' + utcstamp * INTERVAL '1' SECOND )
         AT TIME ZONE 'Europe/Amsterdam' AS Amsterdam_Time
FROM   your_table

Output:

| AMSTERDAM_TIME                                 |
| :--------------------------------------------- |
| 2019-12-18 12:00:00.000000000 EUROPE/AMSTERDAM |

Query 2:

If you want it as a DATE then just wrap everything in a CAST:

SELECT CAST(
         ( TIMESTAMP '1970-01-01 00:00:00 UTC' + utcstamp * INTERVAL '1' SECOND )
           AT TIME ZONE 'Europe/Amsterdam'
         AS DATE
       ) AS Amsterdam_Time
FROM   your_table

Output:

| AMSTERDAM_TIME      |
| :------------------ |
| 2019-12-18 12:00:00 |

db<>fiddle here


CREATE FUNCTION DATE_TO_UTCEPOCHTIME (
  dt IN DATE,
  tz IN VARCHAR2 DEFAULT 'UTC'
) RETURN NUMBER DETERMINISTIC
IS
BEGIN
  RETURN ROUND(
           ( CAST( FROM_TZ( dt, tz ) AT TIME ZONE 'UTC' AS DATE )
             - DATE '1970-01-01' )
           * 24 * 60 * 60
         );
END;
/

CREATE FUNCTION UTCEPOCHTIME_TO_DATE(
  utctime IN NUMBER,
  tz      IN VARCHAR2 DEFAULT 'UTC'
) RETURN DATE DETERMINISTIC
IS
BEGIN
  RETURN ( TIMESTAMP '1970-01-01 00:00:00 UTC' + utctime * INTERVAL '1' SECOND )
           AT TIME ZONE tz;
END;
/

then you can do:

SELECT utcepochtime_to_date( utcstamp, 'Europe/Amsterdam' )
FROM   your_table;

Which outputs:

| UTCEPOCHTIME_TO_DATE(UTCSTAMP,'EUROPE/AMSTERDAM') |
| :------------------------------------------------ |
| 2019-12-18 12:00:00                               |

and

SELECT date_to_utcepochtime(
         DATE '2019-12-18' + INTERVAL '12:00:00' HOUR TO SECOND,
         'Europe/Amsterdam'
       ) AS utcepochtime
FROM   DUAL;

which outputs:

| UTCEPOCHTIME |
| -----------: |
|   1576666800 |

db<>fiddle here

Upvotes: 2

Popeye
Popeye

Reputation: 35920

You can achieve it using the following query where we have used FROM_TZ to convert UTC to Europe/Amsterdam time:

SQL> SELECT
  2      TO_CHAR(FROM_TZ( CAST( DATE '1970-01-01' + 1576666800/(24*60*60) AS TIMESTAMP ), 'UTC' )
  3             AT TIME ZONE 'Europe/Amsterdam', 'yyyy-mm-dd hh24:mi:ss') as "desired_date"
  4  FROM
  5      DUAL;

desired_date
-------------------
2019-12-18 12:00:00

SQL>

Daylight saving is automatically handled when we use the long name of the timezone which is 'Europe/Amsterdam' in our case.

Cheers!!

Upvotes: 1

Related Questions