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

鉴于UTC不是一个时区,而是一个时间标准(例如这里所述 ),为什么在我的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是Windows中的时区

“UTC不是时区”这句话实际上是错的吗?

严格来说,这个说法并没有错。 UTC是一个标准,而不是一个时区 (如你已经链接)。

时区对应于世界上的一些地区,并且在该地区有许多不同的规则:

  • 什么是夏时制和什么时候不是UTC时差(与UTC的区别)
  • 当DST开始和结束
  • 所有这些地区的抵消和DST的变化在其历史上都有

例如:在1985年,英国的巴西状态标准偏差UTC-05:00 (在DST期间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:00或者只是Z

UTC与时区的另一个区别在于,时区是由政府和法律界定的,可随时随地更改。 以上所述的阿克里所有的变化都是由政治家定义的,无论他们当时是怎么想的。 (所以,即使今天一个地区在他们的时区跟随UTC,也不能保证它将来保持不变,这就是为什么即使这些地区有自己的时区,即使它们看起来多余)。

但是无论政治家们多少次改变他们的区域偏移量,他们都必须和UTC相关(当然, 直到有新的标准出现 )。


现在,当你看到像TimeZone.getTimeZone("UTC")这样的实现TimeZone.getTimeZone("UTC") ,你可以用两种不同的方式来思考它:

  • 一个设计上的缺陷,因为它混合了两种不同的概念,并引导人们认为它们是相同的东西
  • 一个快捷方式/简化/ 好戏 /解决方法,使事情变得更容易( @JonSkeet解释他的答案 )。

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


然而, 新的java.time API将两个概念分开: ZoneRegionZoneOffset (实际上两者都是ZoneId子类,但ZoneRegion不公开,所以实际上我们使用ZoneIdZoneOffset ):

  • 如果您使用带有IANA时区名称的ZoneId (始终采用Continent/City格式,如America/Sao_PauloEurope/Berlin ),则会创建一个ZoneRegion对象 – 一个包含所有DST规则的“真实”时区。 所以,根据您在此ZoneId使用的日期,您可以有不同的偏移量。
  • 如果使用ZoneOffset (使用ZUTC ,+ +03:00等),它将只返回一个表示偏移量的对象:与UTC的差异,但不包含任何DST规则。 不管你使用这个对象的日期,它总是和UTC有相同的区别。

所以, ZoneId (实际上是ZoneRegion )与一些地区(在某个时区 )的偏移随着时间的推移而变化(由于DST规则,政治家因为什么而改变东西等)的观点是一致的。 而ZoneOffset代表与UTC不同的观点,即没有DST规则,也不会改变。

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

你仍然可以认为这是一个“错误”的设计决策或简化,使事情变得更容易(或两者兼而有之)。 国际海事组织,这个决定是一个很大的改善,比旧的java.util.TimeZone ,因为它明确指出,UTC不是一个时区(在它没有DST规则,永远不会改变),这只是一个零差UTC标准(一种非常技术性的说法是“它是UTC”)。

它也将时区和偏移量的概念分开(虽然这些概念是非常相关的,但并不是一回事)。 我看到它将UTC定义为一个特殊的偏移量作为“实现细节”。 创建另一个类只是为了处理UTC将是多余的和混乱的,保持它作为一个ZoneOffset是一个很好的决定,简化的事情,并没有搅乱API(对我来说,公平的权衡)。

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

因为它使得生活更加简单,基本上把UTC看作是一个时区,而不是把它当作别的东西。

这是其中之一“ 严格来说,这不是”情景。 除了“观察到世界上哪个地区? 你可以把UTC看作是一个时区,它工作的很好。 所以把它稍微弯曲一点,比把整个单独的概念弯曲起来简单些。

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

如果您将时区视为地理区域以及该映射,那么不会,这样做效果不佳 – 但在软件中这种情况更少。 (你总是可以假装说它是一个空的区域:)