Reputation: 7325
The cookies I create with owa_cookie.send
are getting an additional 8 hours to the expiration date.
The server is using UTC time (The result of select to_char(sysdate, 'hh24:mi') from dual
is the same as the current UTC time). So I don't think the difference is caused by the time zone.
I'm now using the following call to create a cookie (note the -8/24
on the expires
). It works for now, but this doesn't seem very safe.
-- creates a cookie that lasts for 1 hour that can also be seen by JS
-- the value of the cookie is the expiration date in ISO format
owa_cookie.send(
name => 'TEST_DTM',
value => to_char(cast((sysdate + 1/24) as timestamp) at time zone 'UTC', 'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'),
expires => sysdate + (1 - 8) / 24,
path => '/ords',
secure => 'Y',
httponly => null);
Does anybody know where the difference in time is coming from?
Upvotes: 0
Views: 311
Reputation: 168671
You have an implicit cast from a TIMESTAMP
to a TIMESTAMP WITH TIME ZONE
:
to_char(
cast((sysdate + 1/24) as timestamp) -- TIMESTAMP (without time zone)
at time zone 'UTC', -- TIMESTAMP WITH TIME ZONE
'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'
)
This is effectively adding a time zone:
to_char(
cast(sysdate + 1/24 as timestamp with local time zone)
at time zone 'UTC',
'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'
)
Which converts SYSDATE
in the database's time zone to the local time zone (whichever time zone the client application is using, and not the database time zone) and then converts it to UTC.
You would be better to use SYSTIMESTAMP
rather than SYSDATE
and save yourself a lot of confusion about data types and time zones:
TO_CHAR(
(SYSTIMESTAMP + INTERVAL '1' HOUR) AT TIME ZONE 'UTC',
'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"'
)
However, if you really did want to use SYSDATE
then use the database time zone rather than the local (client) time zone:
to_char(
FROM_TZ(CAST(sysdate + 1/24 AS TIMESTAMP), DBTIMEZONE)
at time zone 'UTC',
'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'
)
For example, if the database time is UTC and you do:
ALTER SESSION SET TIME_ZONE = 'Asia/Shanghai';
SELECT 'SYSDATE with implicit local cast' AS method,
to_char(
cast(sysdate + 1/24 as timestamp)
at time zone 'UTC',
'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'
) AS utc_timestamp
FROM DUAL
UNION ALL
SELECT 'SYSDATE with explicit local cast',
to_char(
cast(sysdate + 1/24 as timestamp with local time zone)
at time zone 'UTC',
'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'
)
FROM DUAL
UNION ALL
SELECT 'SYSDATE with explicit DB timezone cast',
to_char(
FROM_TZ(CAST(sysdate + 1/24 AS TIMESTAMP), DBTIMEZONE)
at time zone 'UTC',
'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'
)
FROM DUAL
UNION ALL
SELECT 'SYSTIMESTAMP',
TO_CHAR(
(SYSTIMESTAMP + INTERVAL '1' HOUR) AT TIME ZONE 'UTC',
'YYYY-MM-DD"T"HH24:MI:SS.FF3"Z"'
)
FROM DUAL;
Then the output is:
METHOD UTC_TIMESTAMP SYSDATE with implicit local cast 2021-11-01T04:07:04.000Z SYSDATE with explicit local cast 2021-11-01T04:07:04.000Z SYSDATE with explicit DB timezone cast 2021-11-01T12:07:04.000Z SYSTIMESTAMP 2021-11-01T12:07:04.200Z
db<>fiddle here
Upvotes: 1