Oracle, Daylight Saving Time, And Unix Timestamps ~ Wed, 01 Feb 2012 15:59:59 +0000
Notice: the functions in this post are fragile. See Oracle And Unix Timestamps Revisited for a more robust implementation.
If ever there was a combination to make you hate developing web applications against an Oracle database, it's the one defined in the title of this post. Let's see:
- Unix timestamps are used in a lot of web applications because they're easy to work with
- Oracle doesn't have any native functions for working with Unix timestamps
- You have no way of knowing when a bored government will change the dates that DST starts and ends
- You shouldn't include a timezone in a Unix timestamp
After much searching, and piecing together of different solutions to slightly different problems, I have written the following three functions that should cover all of your Unix timestamp handling needs within an Oracle database:
CREATE OR REPLACE
FUNCTION unix_time
RETURN INTEGER
AS
ut INTEGER := 0;
tz VARCHAR2(8) := '';
BEGIN
/**
* This function is for getting the current number of seconds since
* 01 January 1970 in UTC, i.e. a Unix timestamp.
*
* @author James Sumners
* @date 01 February 2012
*
* @return integer
*/
-- Get the current timezone abbreviation (stupid DST)
SELECT
extract(timezone_abbr FROM CURRENT_TIMESTAMP)
INTO
tz
FROM
dual;
-- Get the Unix timestamp
SELECT
(new_time(sysdate, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (
86400)
INTO
ut
FROM
dual;
RETURN ut;
END unix_time;
CREATE OR REPLACE
FUNCTION unix_time_to_date(
unix_time IN INTEGER,
local_tz IN INTEGER DEFAULT 0
)
RETURN DATE
AS
converted_date DATE;
tz VARCHAR2(8) := '';
BEGIN
/**
* This function is used to convert a Unix timestamp (UTC) into an Oracle DATE. The converted DATE will
* be in UTC unless the optional local_tz parameter is provided.
*
* @author James Sumners
* @date 01 February 2012
*
* @param unix_time The Unix timestamp to convert
* @param local_tz 0 = UTC, 1 = Local database time zone
*
* @return date
*/
SELECT
to_date('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + numtodsinterval(
unix_time, 'SECOND')
INTO
converted_date
FROM
dual;
IF local_tz <> 0 THEN
-- Get the current timezone abbreviation (stupid DST)
SELECT
extract(timezone_abbr FROM CURRENT_TIMESTAMP)
INTO
tz
FROM
dual;
-- Convert the GMT time to the current local timezone
converted_date := new_time(converted_date, 'GMT', tz);
END IF;
RETURN converted_date;
END unix_time_to_date;
CREATE OR REPLACE
FUNCTION unix_time_from_date(
in_date IN DATE
)
RETURN INTEGER
AS
ut INTEGER := 0;
tz VARCHAR2(8) := '';
BEGIN
/**
* This function is used to convert an Oracle DATE (local timezone) to a Unix timestamp (UTC).
*
* @author James Sumners
* @date 01 February 2012
*
* @param in_date An Oracle DATE to convert. It is assumed that this date will be in the local timezone.
*
* @return integer
*/
-- Get the local timezone from the passed in date
SELECT
extract(timezone_abbr FROM CAST(in_date AS TIMESTAMP
WITH
local TIME zone))
INTO
tz
FROM
dual;
-- Get the Unix timestamp
SELECT
(new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (
86400)
INTO
ut
FROM
dual;
RETURN ut;
END unix_time_from_date;
Comments
Oracle And Unix Timestamps Revisited « Room Full of Mirrors said (2012-02-10 18:35:18 GMT):
[...] « Oracle, Daylight Saving Time, And Unix Timestamps [...]