夏令时与Oracle的时差

时间:2018-07-26 08:43:09

标签: oracle

我们正在尝试对日期进行算术运算。我们正尝试增加1天(24小时),这是一个基本示例...

select to_date('2018-10-06 22:00:00') + 1 from dual;

我们从中得到的结果如下...

2018-10-07 22:00:00

从表面上看,这看起来不错,但是我们处于悉尼时区,并且在那个过渡时期出现了夏令时,所以时间应该更像这样……

2018-10-07 23:00:00

所以我想我的问题是,在oracle中进行算术运算时是否可以考虑夏令时。一个想法是将初始日期转换为UTC并转换回悉尼时间,但这似乎是一个复杂的解决方案,可能已经由某处的oracle功能处理了。

欢呼

1 个答案:

答案 0 :(得分:2)

您实际上不能直接用日期来完成操作,因为这些日期不支持时区。

您可以从带有时区的时间戳开始,例如作为时间戳文字:

select timestamp '2018-10-06 22:00:00 Australia/Sydney' + interval '1' day
from dual;

TIMESTAMP'2018-10-0622:00:00AUSTRALIA/SYDNEY'+
----------------------------------------------
2018-10-07 23:00:00.000000000 AUSTRALIA/SYDNEY

如果您要舍弃该信息,可以将其回溯到日期:

select cast(timestamp '2018-10-06 22:00:00 Australia/Sydney' + interval '1' day as date)
from dual;

CAST(TIMESTAMP'2018
-------------------
2018-10-07 23:00:00

如果您从某个日期开始,例如在表格列中,您可以将其强制转换为时间戳并指定时区:

with your_table (your_date) as (
  select to_date('2018-10-06 22:00:00') from dual
)
select from_tz(cast(your_date as timestamp), 'Australia/Sydney') + interval '1' day
from your_table;

FROM_TZ(CAST(YOUR_DATEASTIMESTAMP),'AUSTRALIA/
----------------------------------------------
2018-10-07 23:00:00.000000000 AUSTRALIA/SYDNEY

,并且有选择地再次回溯到日期,以丢弃小数秒和时区信息。

如果您的会话时区是悉尼,那么可以通过强制转换为timestamp with time zone来隐式设置该时间:

with your_table (your_date) as (
  select to_date('2018-10-06 22:00:00') from dual
)
select cast(your_date as timestamp with time zone) + interval '1' day
from your_table;

但是通常最好不要假设任何会运行代码的会话环境。


当时钟在DST结束时返回时,您可以通过包含DST指示器来指定02:00到03:00之间两个可能的时间值中的哪个:

alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZH:TZM';

select timestamp '2018-04-01 01:00:00 Australia/Sydney AEDT' from dual;

TIMESTAMP'2018-04-0101:00:
--------------------------
2018-04-01 01:00:00 +11:00

select timestamp '2018-04-01 02:00:00 Australia/Sydney AEDT' from dual;

TIMESTAMP'2018-04-0102:00:
--------------------------
2018-04-01 02:00:00 +11:00

select timestamp '2018-04-02 02:00:00 Australia/Sydney AEST' from dual;

TIMESTAMP'2018-04-0202:00:
--------------------------
2018-04-02 02:00:00 +10:00

select timestamp '2018-04-01 03:00:00 Australia/Sydney AEST' from dual;

TIMESTAMP'2018-04-0103:00:
--------------------------
2018-04-01 03:00:00 +10:00

尽管对我来说,这似乎仅在12.2.0.1中有效;在早期版本中,无法识别AEST / AEDT(尽管EST是)。我不确定这是否只是时区文件的版本-我的12.2实例的版本是26。

如果在DST开始时时钟前进时,如果您所看到的时间似乎不存在于小时中,那么可以采用其他方法,因为它们无效,因此您无能为力。如果使用sysdate填充字段,并且服务器设置为Sydney或current_date且会话设置为,则不会发生这种情况。使用to_date()创建的日期可能在该窗口中,但是您可能需要弄清楚原因并停止这种情况。