将SimpleDateFormatter与时区一起使用时出现意外结果

时间:2017-08-30 17:30:02

标签: java date timezone timestamp timezone-offset

我的目标是使用格式yyyy-MM-dd hh:mm:ss.SSS解析给定时区的日期字符串,仅使用Java 6而不使用任何外部库。我的第一种方法是使用时区配置SimpleDateFormatter。但是,我无法理解结果。看看下面的代码:

List<String> zones = Arrays.asList("UTC", "CET", "Europe/London", "Europe/Berlin");

for(String zone: zones) {
  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
  df.setTimeZone(TimeZone.getTimeZone(zone));
  Date result =  df.parse("1970-01-01 00:00:00.000");
  System.out.println(zone + ": " + result.getTime()); 
}

输出如下:

UTC: 0
CET: -3600000
Europe/London: -3600000
Europe/Berlin: -3600000

前两个结果如预期。在UTC中,unix时期恰好在零毫秒时开始,与CET存在一小时的差异。

我不明白的是伦敦和柏林的价值观。由于伦敦的毫秒等于CET而不是UTC的毫秒数,我首先假设夏令时被考虑在内(因为它目前在北半球是夏天,而伦敦的夏季是{{1}等于UTC+1)。但是,为什么柏林的价值相同呢?不应该是CET(或UTC+2,如果你想要的话)?

我的问题:

  • 结果的解释是什么? CET+1是否真的被考虑在内了?
  • 在Java 6中进行转换是否有更好的方法?

1 个答案:

答案 0 :(得分:2)

结果是正确的,因为这是1970年LondonBerlin使用的偏移量(均使用+01:00)。

它与夏令时无关,因为现在它们在3月和10月在这些国家发生。 实际上,人们可能会争辩说,伦敦是一个长期的&#34; DST期间,从1968年到1971年,因为在整个期间的偏差为+01:00

这只是时区的本质:它们由政府和法律界定,各自的政治家可以根据他们的原因改变他们国家所使用的抵消。

在上面的相同链接中,您可以看到柏林仅在1980年采用了DST,而伦敦在1971年将偏移量改为零(GMT)。

PS:正如评论中所讨论的那样,CET这样的短名称是ambiguous and not standard(对于他们中的很多人来说,还有more than one timezone that uses the same abbreviation)。始终更喜欢使用IANA timezones names(始终采用Region/City格式,例如America/Sao_PauloEurope/Berlin

某些名称(例如CET)被识别并设置为任意默认值 - 主要是由于复古兼容性(或不良设计)问题 - 但它通常以意想不到的方式完成。如果可以的话,请避免使用这样的简短名称:Europe/Berlin之类的名称更清晰,没有含糊之处。