Our data is stored at the timezone UTC+00:00.
To make some query, we have to convert our timestamp input from 'Europe/Paris' time zone to UTC+00:00 ie Europe/London. And when we get this data, convert the output timestamp to 'Europe/Paris' time zone.
So the solution that I found was to use the "at time zone" like cast(VALIDATIONTIME as timestamp) at time zone 'Europe/Paris'
It works with the input but not with the output(when we get data).
So how to make it to work for the input and the output?
Example:
Orders table
ID VALIDATIONTIME
9986 14/03/16 09:47:29,823000000
6764 20/03/16 12:07:39,453000000
To get the row id 9986, the query would be:
select cast(VALIDATIONTIME as timestamp) at time zone 'Europe/Paris' as validation
from orders
where VALIDATIONTIME between cast(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS') as timestamp) at time zone 'UTC'
and cast(TO_TIMESTAMP('14/03/2016 10:50:18', 'DD/MM/YYYY HH24:MI:SS') as timestamp) at time zone 'UTC';
But the output (validation) doesn't change!!
The at time zone
syntax converts a timestamp with time zone value from it's current zone to the one you specify. When you apply it to a plain timestamp without a timezone, as you are following your cast()
, there's an implicit conversion to the session time zone first.
I think you're really looking for the from_tz()
function :
select VALIDATIONTIME at time zone 'Europe/Paris' as validation
from orders
where VALIDATIONTIME between
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris')
and
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:50:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris');
You can see the generated time with a standalone query; this also converts the time specified as being in the Paris time zone to UTC for comparison:
select
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris')
as Paris,
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris')
at time zone 'UTC' as London
from dual;
PARIS LONDON
------------------------------------------ ------------------------------------------
14-MAR-16 10.45.18.000000000 EUROPE/PARIS 14-MAR-16 09.45.18.000000000 UTC
(Of course, London isn't UTC in the summer, but we'll ignore that detail for now; I'll assume you actually want UTC and not London).
You may have to manipulate validationtime
more depending on its data type and the session time zone. With some simple data setup and validationtime
as a plain timestamp (with no time zone info):
create table orders (id number, validationtime timestamp);
insert into orders (id, validationtime)
values (9986, to_timestamp('14/03/16 09:47:29,823000000', 'DD/MM/RR HH24:MI:SS,FF'));
insert into orders (id, validationtime)
values (6764, to_timestamp('20/03/16 12:07:39,453000000', 'DD/MM/RR HH24:MI:SS,FF'));
If my session is on London time then the basic query works:
alter session set time_zone = 'Europe/London';
select VALIDATIONTIME at time zone 'Europe/Paris' as validation
from orders
where VALIDATIONTIME between
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris')
and
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:50:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris');
VALIDATION
------------------------------------------
14-MAR-16 10.47.29.823000000 EUROPE/PARIS
But if I changer the session time zone to Paris then now it doesn't:
alter session set time_zone = 'Europe/Paris';
select VALIDATIONTIME at time zone 'Europe/Paris' as validation
from orders
where VALIDATIONTIME between
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris')
and
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:50:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris');
no rows selected
So you need to specify that the original timestamp in your table it UTC, which you can do with the same function:
select FROM_TZ(VALIDATIONTIME, 'UTC') at time zone 'Europe/Paris' as validation
from orders
where FROM_TZ(VALIDATIONTIME, 'UTC') between
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris')
and
FROM_TZ(TO_TIMESTAMP('14/03/2016 10:50:18', 'DD/MM/YYYY HH24:MI:SS'), 'Europe/Paris');
VALIDATION
------------------------------------------
14-MAR-16 10.47.29.823000000 EUROPE/PARIS
Essentially you need to make sure all the dates you're using are in the same zone before you compare them. Another way is to force the variable dates to UTC and then to plain timestamps:
select FROM_TZ(VALIDATIONTIME, 'UTC') at time zone 'Europe/Paris' as validation
from orders
where VALIDATIONTIME
between
cast(FROM_TZ(TO_TIMESTAMP('14/03/2016 10:45:18', 'DD/MM/YYYY HH24:MI:SS'),
'Europe/Paris') at time zone 'UTC' as timestamp)
and
cast(FROM_TZ(TO_TIMESTAMP('14/03/2016 10:50:18', 'DD/MM/YYYY HH24:MI:SS'),
'Europe/Paris') at time zone 'UTC' as timestamp);
VALIDATION
------------------------------------------
14-MAR-16 10.47.29.823000000 EUROPE/PARIS
... which looks more complicated but as it doesn't modify the table column in the where
clause it will allow any index on that column to still be used.
Here the variable string is converted to a plain timestamp, declared as being in the Paris time zone, converted to UTC, and then cast back to a plain timestamp - so it's in the same format and (implied) time zone as the table column data.
Oracle Setup :
CREATE TABLE orders (
ID INT,
VALIDATIONTIME TIMESTAMP
);
INSERT INTO orders VALUES (
9968,
FROM_TZ( TIMESTAMP '2016-03-14 09:47:29.823', 'Europe/Paris' )
AT TIME ZONE 'UTC'
);
-- Alternate syntax for inserting from TZ:
INSERT INTO orders VALUES (
6764,
TO_TIMESTAMP_TZ( '2016-03-20 20:07:39.453 Europe/Paris',
'YYYY-MM-DD HH24:MI:SS.FF TZR' )
AT TIME ZONE 'UTC'
);
Or even simpler:
INSERT INTO orders VALUES (
9968,
TIMESTAMP '2016-03-14 09:47:29.823+01:00' AT TIME ZONE 'UTC'
);
or:
INSERT INTO orders VALUES (
6764,
TIMESTAMP '2016-03-20 20:07:39.453 Europe/Paris' AT TIME ZONE 'UTC'
);
Query 1 :
SELECT * FROM orders;
ID VALIDATIONTIME
---- -----------------------------
9986 2016-03-14 08:47:29.823000000
6764 2016-03-20 19:07:39.453000000
(This shows the UTC time in the table)
Query 2 :
SELECT id,
CAST( VALIDATIONTIME AS TIMESTAMP WITH TIME ZONE )
AT TIME ZONE 'Europe/Paris' AS validationtime
FROM orders
ID VALIDATIONTIME
---- ------------------------------------------
9986 2016-03-14 09:47:29.823000000 EUROPE/PARIS
6764 2016-03-20 20:07:39.453000000 EUROPE/PARIS
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.