繁体   English   中英

将时间戳字段转换为正确的时区

[英]Converting timestamp field to proper time zone

我们的数据存储在UTC + 00:00时区。

要进行查询,我们必须将时间戳输入从“欧洲/巴黎”时区转换为UTC + 00:00,即欧洲/伦敦。 当我们获得这些数据时,将输出时间戳转换为“欧洲/巴黎”时区。

因此,我发现的解决方案是cast(VALIDATIONTIME as timestamp) at time zone 'Europe/Paris'时区使用诸如cast(VALIDATIONTIME as timestamp) at time zone 'Europe/Paris'类的“在时区” cast(VALIDATIONTIME as timestamp) at time zone 'Europe/Paris'它适用于输入,但不适用于输出(当我们获得数据时)。

那么如何使其适用于输入和输出呢?

例:

Orders table
ID      VALIDATIONTIME
9986    14/03/16 09:47:29,823000000
6764    20/03/16 12:07:39,453000000

要获取行ID 9986,查询将是:

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';

但是输出(验证)没有改变!

at time zone语法会将带有时区值的时间戳从当前时区转换为您指定的时间戳。 当您将其应用于没有时区的普通时间戳时,正如您跟随cast() ,首先会隐式转换为会话时区。

我认为您确实在寻找from_tz()函数

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');

您可以通过独立查询查看生成的时间; 这还将指定的巴黎时区中的时间转换为UTC进行比较:

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          

(当然,夏天夏天伦敦不是UTC,但现在我们将忽略该细节;我假设您实际上是要使用UTC,而不是伦敦)。

您可能必须根据其数据类型和会话时区validationtime更多地操作validationtime时间。 通过简单的数据设置和validationtime作为普通时间戳(无时区信息):

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'));

如果我的会议是在伦敦时间,则基本查询有效:

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 

但是,如果我将会话时区更改为巴黎,那么现在不会:

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

因此,您需要将表中的原始时间戳记指定为UTC,您可以使用相同的功能执行此操作:

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 

本质上,在比较之前,您需要确保所使用的所有日期都在同一区域中。 另一种方法是将可变日期强制为UTC,然后强制为普通时间戳:

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 

...看起来更复杂,但是由于它不会修改where子句中的table列,因此它将允许该列上的任何索引继续使用。

在这里,变量字符串将转换为纯时间戳,声明为位于巴黎时区,转换为UTC,然后转换回纯时间戳-因此,其格式与表列数据的格式和(隐含)时区相同。

Oracle安装程序

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'
);

甚至更简单:

INSERT INTO orders VALUES (
  9968,
  TIMESTAMP '2016-03-14 09:47:29.823+01:00' AT TIME ZONE 'UTC'
);

要么:

INSERT INTO orders VALUES (
  6764,
  TIMESTAMP '2016-03-20 20:07:39.453 Europe/Paris' AT TIME ZONE 'UTC'
);

查询1

SELECT * FROM orders;

  ID VALIDATIONTIME
---- -----------------------------
9986 2016-03-14 08:47:29.823000000
6764 2016-03-20 19:07:39.453000000

(这在表中显示了UTC时间)

查询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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM