为什么UTC(不是时区)被认为是Java中的时区(而不仅仅是那里)?

时间:2017-06-26 09:16:00

标签: java windows timezone utc timezone-offset

鉴于UTC不是时区,而是时间标准(如所述,例如here),为什么在我的Java应用程序中我可以使用UTC,就好像它是一个时区(参见代码)下面的片段?)

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("UTC"));

如果UTC不是时区,为什么TimeZone.getTimeZone("UTC")能够返回时区对象?

顺便说一下,在我的Windows机器上,UTC也在时区列表中(见截图)。

声明" UTC不是时区"实际上错了?

UTC is a time zone in Windows

2 个答案:

答案 0 :(得分:12)

因为它将生命周期视为一个时区比将其视为其他东西要简单得多,简单得多。

这是其中之一“是的,严格来说它不是”场景。除了“观察到世界哪个地区?”之外的所有事情。您可以将UTC视为时区,它可以正常工作。因此,将其略微弯曲变形比使用完全独立的概念更简单。

如果您将时区视为从“即时”到“UTC偏移”(或等效,从“即时”到“本地观察时间”)的映射,则可以将UTC视为时间区域 - 这是我们在软件中所做的大部分工作。

如果您将时区视为地理区域以及该映射,那么不,它不起作用 - 但这在软件中很少有用。 (并且你可以通过说它是一个空的区域来伪造它:)

答案 1 :(得分:6)

  

声明“UTC不是时区”实际上是错误的吗?

从技术上讲,严格来说,声明并没有错。 UTC is a standard, not a timezone(正如您已经链接过的那样)。

时区对应于世界上的某个地区,并且对该地区有很多不同的规则:

  • 什么是UTC偏移(与UTC的差异)在夏令时和什么时候不是
  • 当DST开始和结束时
  • 此区域的偏移和DST的所有更改在其历史记录中

示例:在1985年,巴西的Acre国家在DST期间有标准偏移UTC-05:00(和UTC-04:00),然后在1988年它没有DST的UTC-05:00,然后在2008年标准更改为UTC-04:00(并且没有DST),自2013年起,它又回到UTC-05:00而没有DST。

虽然时区会跟踪所有这些更改,但UTC没有此类规则。您可以通过多种不同的方式来考虑UTC:

  • “基础”日期/时间,与其他人相关的日期/时间 - 与UTC的这种差异称为“偏移”。今天,圣保罗位于UTC-03:00(偏移减去3小时,或比UTC晚3小时),而东京在UTC+09:00(偏移<强>加9小时) ,或提前9小时UTC)。
  • 一个永不变化的“特殊”时区。它始终处于相同的偏移量(零),它永远不会改变,并且永远不会有DST转换。

由于“UTC的偏移量”(不确定该术语的技术准确度)始终为零,因此通常写为UTC+00:00Z

UTC和时区之间的另一个区别是,时区是由政府和法律定义的,可以随时随地进行更改。上述Acre的所有变化都是由政治家定义的,无论他们当时想到什么。 (因此,即使今天的某个地区在其时区中遵循UTC,也不能保证它在未来会保持不变,这就是为什么即使这些地区也有自己的时区,即使它们看起来多余了。)

但无论政治家多少次改变他们的地区抵消,他们必须相对于UTC(until a new standard comes up,当然)。

现在,当您看到TimeZone.getTimeZone("UTC")等实施时,您可以通过两种不同的方式来考虑它:

  • 一个设计缺陷,因为它混合了两个不同的概念,并引导人们认为它们是同一个东西
  • 快捷方式/简化/好玩法/解决方法,使事情变得更轻松(如@JonSkeet explained in his answer)。

对我来说,这是两者的混合(五十/五十)。

new java.time API分隔了两个类中的概念:ZoneRegionZoneOffset(实际上它们都是ZoneId的子类,但ZoneRegion不是公众所以实际上我们使用ZoneIdZoneOffset):

  • 如果您使用ZoneId IANA timezones names(始终采用Continent/City格式,如America/Sao_PauloEurope/Berlin),则会创建{{1} object - 一个“真实”的时区,包含所有DST规则和历史记录中的偏移量。因此,根据您在此ZoneRegion
  • 中使用的日期,您可以使用不同的偏移量
  • 如果您使用ZoneIdZoneOffsetZUTC等),它将只返回一个表示偏移量的对象:与UTC,但没有任何DST规则。无论您使用此对象的日期,它始终与UTC具有相同的差异。

因此,+03:00(实际上ZoneId)与某些区域(某些时区)的偏移量随时间变化的想法一致(由于DST规则,政治家改变事物,因为无论如何等)。并且ZoneRegion表示与UTC 的差异,没有DST规则且永远不会更改。

还有一个特殊的常量ZoneOffset,它表示与UTC(UTC本身)的差异。请注意,新API采用了不同的方法:不是说所有内容都是时区而且UTC是特殊类型,它表示UTC是ZoneOffset.UTC,其偏移值为零。

您仍然可以认为这是一个“错误的”设计决策或简化使事情变得更容易(或两者兼而有之)。 IMO,与旧的ZoneOffset相比,这个决定是一个很大的进步,因为它清楚地表明UTC不是一个时区(在某种意义上它没有DST规则而且永远不会改变),它只是与UTC标准(一种非常技术性的说法“它是UTC”)。

它还将时区和偏移的概念分开(虽然彼此非常相关,但这些概念并不相同)。我看到它将UTC定义为特殊偏移量作为“实现细节”。创建另一个只是处理UTC的类将是多余的并且令人困惑,并且将其保持为java.util.TimeZone是一个很好的决定,简化了事情并且没有弄乱API(对我来说,这是一个公平的权衡)。

我相信许多其他系统决定采用类似的方法(这解释了Windows在时区列表中有UTC的原因)。