当时区规则发生变化时,如何在Java中映射到历史上准确的本地时间?

当时区规则发生变化时,如何在Java中映射到历史上准确的本地时间?,java,time,calendar,timezone,gregorian-calendar,Java,Time,Calendar,Timezone,Gregorian Calendar,我有一个包含UTC(GMT+0)时间戳的数据库。问题是:它们指的是印第安纳州发生的计费活动 一些人可能知道,印第安纳州 在2006年之前根本不遵守夏令时(该州大部分地区全年都是东部夏令时) 2006年投票决定保留美国东部标准时间,但开始与美国其他地区实行夏令时 2007年修订了其规则;美国联邦政府修改了夏令时,从而改变了开始和结束规则 由于此数据库中的时间戳指的是政府计费活动,因此实际上有必要将UTC时间戳报告为历史上准确的本地时间,以保持审计准确性。因此,有三种情况特别适用于印第安纳州:2

我有一个包含UTC(GMT+0)时间戳的数据库。问题是:它们指的是印第安纳州发生的计费活动

一些人可能知道,印第安纳州

  • 在2006年之前根本不遵守夏令时(该州大部分地区全年都是东部夏令时)
  • 2006年投票决定保留美国东部标准时间,但开始与美国其他地区实行夏令时
  • 2007年修订了其规则;美国联邦政府修改了夏令时,从而改变了开始和结束规则
由于此数据库中的时间戳指的是政府计费活动,因此实际上有必要将UTC时间戳报告为历史上准确的本地时间,以保持审计准确性。因此,有三种情况特别适用于印第安纳州:2006年之前的时间戳使用的时区规则与2006-2007年之间的完全不同,而2007年之后的时间戳使用的时区规则则完全不同。您可以想象,该数据库包含印第安纳州以外地区的活动,因此事情变得更加复杂

Java Calendar and TimeZone API不包含允许程序员创建具有多组时区规则的对象的任何类,因此,如果特定的、适用的时区规则发生变化,则无法使用这些类将UTC时间戳正确映射到历史上准确的本地时间

我考虑过如何解决在时区规则不断变化的地区中映射到历史上准确的本地时间的问题

  • 数据库可以更新,以便UTC时间戳可以与本地时间偏移和夏令时偏移一起存储。这里的问题是数据库的大小增加了一点,如果现有数据库很大,那么更新所有表可能需要延长脱机维护周期

  • 可以更新数据库,以便与该特定时间戳相应的特定时区对象与每个时间戳一起存储。虽然我认为时区对象非常轻量级,但我认为这比上面的更灵活,但仍然不太理想,因为它需要为每个时间戳持久化一个对象

  • 可以开发一个自定义API,该API可以从历史上精确的感兴趣地区规则数据库中构建适当的时区对象。此解决方案将前两个解决方案增加的存储需求替换为对额外处理的需求。需要显示的每个时间戳都意味着创建一个新对象。。。或者至少与对象池中的适当对象配对。此外,它还意味着创建和管理时区数据库

Java Time和Calendar API的局限性使得为这个问题找到一个优雅的解决方案变得非常困难(例如,如果不编写一些非常混乱的代码,就不能查询现有的SimpleTimeZone对象并询问它遵循什么夏令时规则)


我只想问一下,以前是否有人处理过类似的情况,以及他们是如何处理的

您描述的时区数据库已经存在。它被称为奥尔森zoneinfo数据库,它适用于1970年之后的所有日期,并且

更好的是,Java的原生日期和时间API使用这个数据库。您可以使用
java.util.TimeZone.getTimeZone()
加载任意时区,并使用此对象获取偏移量或执行转换(例如,使用
TimeZone.getOffset(long)
。例如,您可以加载
“America/Indiana/Indianapolis”
区域以转换印第安纳州的日期和时间


使用
时区
数据库有一件事是很难做到的,那就是查询它使用的规则。为此,我相信你必须直接深入tz文件。不过,在大多数情况下,只获取指定日期的偏移量就足够了。

我不懂Java,但我很确定它使用的是(由合同内容证明)如果是这样的话,你就不用担心了。奥尔森数据库处理所有的历史规则,应该给你正确的当地时间。很遗憾,我们必须努力清理政客的垃圾。印第安纳州有多个分区:对;印第安纳波利斯分区是八个选项之一。你能举一些例子说明如何执行转换或获取历史上某个特定时刻的时区偏移,即某个给定时间?