在 DST 规则更改后从 UTC 日期时间检索历史本地日期时间



假设我正在使用Oracle SGBD(RDBMS(和Java 8。

我以 UTC 时区存储了历史日期时间,但我的应用程序仅显示本地日期时间,并且我的统计计算也仅适用于本地日期时间。

现在,假设欧洲的 DST 规则按计划发生了变化。

保持我的应用程序和统计信息正常运行的最简单方法是什么?

到目前为止,我读到的是,在Oracle和Java中都有与DST规则相关的时区,但它们不会自动更新。此外,我想做的是保留更改前后的规则,而不仅仅是更新规则,因为我需要历史统计数据,所以我需要"更改前的欧洲/巴黎"时区和"更改后的欧洲/巴黎"时区,或者更好的时区与规则的历史相关联根据需要应用自己。

此外,即使在Java中有一些方便的方法可以做到这一点,它也应该在Oracle中修复以涵盖所有用例。

以下是芝加哥相关的历史规则变化之一。DST 从 1954 年到 9 月的最后一个星期日结束,然后从 1955 年开始结束 10 月的最后一个星期日(直到下一次规则更改(:

DST 开始(时钟向前(-> DST 结束(时钟向后(1953 迪曼奇 26 艾弗里尔, 02 h 00 -> 迪曼奇 27 九月, 02 h 00 1954 迪曼奇 25 艾弗里尔, 02 h 00 -> 迪曼奇 26 九月, 02 h 00 1955 迪曼奇 24 艾弗里尔, 02 h 00 -> 迪曼奇 30 十月, 02 h 00





1956 迪曼奇 29 艾弗里尔, 02 h 00 -> 迪曼奇 28 十月, 02 小时 00

PS:我知道IANA历史时区数据库,但如果您已经这样做了,请展示如何实际将其用于Oracle SGBD和Java。

P.P.S. :任何关于在未来数据库中处理此问题比"UTC"更好的建议也是受欢迎的。

Java 或 Oracle 将自动对任何 UTC 日期应用正确的规则 - 当然,只要您拥有最新的时区数据文件。

由于您询问了 Oracle (SGBD/RDBMS( 方法并提到了芝加哥,因此生成时钟在不同规则下更改的示例日期相当简单,并查看更改应用于正确的日期(与添加到问题中的示例规则更改相比,https://www.timeanddate.com/time/zone/usa/chicago(。

alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZH:TZM';
with t (utc) as (
select timestamp '1954-04-25 07:59:59 UTC' from dual
union all select timestamp '1954-04-25 08:00:00 UTC' from dual
union all select timestamp '1954-09-26 06:59:59 UTC' from dual
union all select timestamp '1954-09-27 07:00:00 UTC' from dual
--
union all select timestamp '1955-04-24 07:59:59 UTC' from dual
union all select timestamp '1955-04-24 08:00:00 UTC' from dual
union all select timestamp '1955-10-30 06:59:59 UTC' from dual
union all select timestamp '1955-10-30 07:00:00 UTC' from dual
--
union all select timestamp '1974-01-06 07:59:59 UTC' from dual
union all select timestamp '1974-01-06 08:00:00 UTC' from dual
union all select timestamp '1974-10-27 06:59:59 UTC' from dual
union all select timestamp '1974-10-27 07:00:00 UTC' from dual
--
union all select timestamp '1975-02-23 07:59:59 UTC' from dual
union all select timestamp '1975-02-23 08:00:00 UTC' from dual
union all select timestamp '1975-10-26 06:59:59 UTC' from dual
union all select timestamp '1975-10-26 07:00:00 UTC' from dual
--
union all select timestamp '1987-04-05 07:59:59 UTC' from dual
union all select timestamp '1987-04-05 08:00:00 UTC' from dual
union all select timestamp '1987-10-25 06:59:59 UTC' from dual
union all select timestamp '1987-10-25 07:00:00 UTC' from dual
--
union all select timestamp '2007-03-11 07:59:59 UTC' from dual
union all select timestamp '2007-03-11 08:00:00 UTC' from dual
union all select timestamp '2007-11-04 06:59:59 UTC' from dual
union all select timestamp '2007-11-04 07:00:00 UTC' from dual
)
select utc,
utc at time zone 'America/Chicago' as chicago
from t;

这为您提供:

UTC                        CHICAGO                   
-------------------------- --------------------------
1954-04-25 07:59:59 +00:00 1954-04-25 01:59:59 -06:00
1954-04-25 08:00:00 +00:00 1954-04-25 03:00:00 -05:00
1954-09-26 06:59:59 +00:00 1954-09-26 01:59:59 -05:00
1954-09-27 07:00:00 +00:00 1954-09-27 01:00:00 -06:00
1955-04-24 07:59:59 +00:00 1955-04-24 01:59:59 -06:00
1955-04-24 08:00:00 +00:00 1955-04-24 03:00:00 -05:00
1955-10-30 06:59:59 +00:00 1955-10-30 01:59:59 -05:00
1955-10-30 07:00:00 +00:00 1955-10-30 01:00:00 -06:00
1974-01-06 07:59:59 +00:00 1974-01-06 01:59:59 -06:00
1974-01-06 08:00:00 +00:00 1974-01-06 03:00:00 -05:00
1974-10-27 06:59:59 +00:00 1974-10-27 01:59:59 -05:00
1974-10-27 07:00:00 +00:00 1974-10-27 01:00:00 -06:00
1975-02-23 07:59:59 +00:00 1975-02-23 01:59:59 -06:00
1975-02-23 08:00:00 +00:00 1975-02-23 03:00:00 -05:00
1975-10-26 06:59:59 +00:00 1975-10-26 01:59:59 -05:00
1975-10-26 07:00:00 +00:00 1975-10-26 01:00:00 -06:00
1987-04-05 07:59:59 +00:00 1987-04-05 01:59:59 -06:00
1987-04-05 08:00:00 +00:00 1987-04-05 03:00:00 -05:00
1987-10-25 06:59:59 +00:00 1987-10-25 01:59:59 -05:00
1987-10-25 07:00:00 +00:00 1987-10-25 01:00:00 -06:00
2007-03-11 07:59:59 +00:00 2007-03-11 01:59:59 -06:00
2007-03-11 08:00:00 +00:00 2007-03-11 03:00:00 -05:00
2007-11-04 06:59:59 +00:00 2007-11-04 01:59:59 -05:00
2007-11-04 07:00:00 +00:00 2007-11-04 01:00:00 -06:00

您可以通过查询v$timezone_file视图或最新版本的database_properties视图来查看您正在使用的时区数据文件的版本。

您可以在 Oracle 支持文档 412160.1(Oracle RDBMS 和 OJVM 时区文件修补程序中更新的 DST 转换和新时区(中阅读有关 Oracle 时区文件版本和修补程序的更多信息。

特别是,请查看J节,"RDBMS DST更新中的更新时区列表",其中说:

所有时区文件更新都是累积的,这意味着较新的RDBMS DST补丁具有以前更新的所有更改。
...
在下面的列表中,列出了在时区文件版本中更新的时区。还列出了此时区时区规则更改的第一年,以及最后一年(如果适用(。

因此,它显示历史日期也包括在内。

从 https://www.oracle.com/technetwork/java/javase/tzdata-versions-138805.html:

下表显示了时区数据的版本包含在 不同版本的 Java 开发工具包 (JDK( 软件和 TZUpdater 工具。有关时区内容的更多信息 数据发布载于相关的增强请求中 (RFE(为该版本。时区发生重大更改的位置 包含在时区数据发布中,这在上一个 列。

最新的 TZdata 版本可从 IANA TZdata 页面找到。

自 TZUpdater v2.0 发布以来,用户现在可以更新 tzdata 使用直接从 IANA 获得的数据的 JDK/JRE 版本 Tzdata发布。有关更多详细信息,请参阅 TZUpdater 自述文件。

如果您想了解 Java SE 中的时区数据更新 平台和 TZUpdater 工具一旦发生,订阅 时区数据版本 RSS 源。

因此,基本上,如果您始终需要最新的时区数据,请使用TZUpdater工具升级Java时区信息。

亚历克斯·普尔在评论中的更新

Oracle/Java将应用UTC日期生效的相应规则 您正在尝试转换为特定时区。你不需要 显式执行任何操作 - 您只需要最新版本的 当前+历史规则