Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将SimpleDataFormatter与时区一起使用时出现意外结果_Java_Date_Timezone_Timestamp_Timezone Offset - Fatal编程技术网

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

Java 将SimpleDataFormatter与时区一起使用时出现意外结果,java,date,timezone,timestamp,timezone-offset,Java,Date,Timezone,Timestamp,Timezone Offset,我的目标是只使用Java6,不使用任何外部库,为给定时区解析格式为yyyy-MM-dd hh:MM:ss.SSS的日期字符串。我的第一种方法是使用时区配置SimpleDataFormatter。然而,我无法理解结果。请查看以下代码: List<String> zones = Arrays.asList("UTC", "CET", "Europe/London", "Europe/Berlin"); for(String zone: zones) { SimpleDateForm

我的目标是只使用Java6,不使用任何外部库,为给定时区解析格式为
yyyy-MM-dd hh:MM:ss.SSS
的日期字符串。我的第一种方法是使用时区配置
SimpleDataFormatter
。然而,我无法理解结果。请查看以下代码:

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
中,unix纪元从零毫秒开始,与
CET
相差一小时

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


我的问题是:

  • 对结果的解释是什么?是否真正考虑了DST
  • 在Java6中有更好的转换方法吗
结果是正确的,因为这是1970年和1970年使用的偏移量(均使用
+01:00

这与夏令时无关,因为现在这些国家的夏令时发生在3月和10月。实际上,有人可能会说伦敦处于一个“长”的DST时期,从1968年到1971年,因为在整个时期内偏移量是
+01:00

这只是时区的性质:它们由政府和法律定义,各自的政治家可以出于任何理由改变他们国家使用的补偿

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


PS:正如评论中所讨论的那样,像
CET
这样的短名称是(对于很多人来说,有)。始终喜欢使用(始终采用
地区/城市
格式,如
美国/圣保罗
欧洲/柏林


一些名称(如
CET
)被识别并设置为任意默认值-主要是由于复古兼容性(或糟糕的设计)问题-但通常以意外的方式完成。尽可能避免使用这样短的名字:像
Europe/Berlin
这样的名字要清楚得多,没有歧义。

伦敦在协调世界时1970-1-1 00:00:00全年都处于夏令时。(实际上是在1968年10月27日至1971年10月31日之间)。因此,它的UTC偏移量与柏林相同。CET不是一个实时时区。你可能想要并且得到了在夏天有CEST的时区的“冬天的一半”。但是,尽可能避免使用三个字母和四个字母的缩写。它们通常模棱两可,不标准化。Java只能识别其中的一小部分,有时还会以令人惊讶的方式解释它们。“你的时区是怎么来的,这会让你明白一个日期是在一年中的下半年,我不敢告诉你。”@OleV.V。是的,我以为是CET。感谢您的解释。我相信您的格式模式字符串中有一个错误:小写的
hh
表示从1到12的AM或PM内的小时,但您使用它来匹配
00
,并且您的日期时间字符串中没有AM或PM。您可能打算在一天中从0到23的一小时内使用
HH
。很明显,这个bug没有改变你的结果。这是一个进入我的肥皂盒的机会。:-)当您选择Java6而不使用任何外部库(如)时,经常会遇到这种情况。众所周知,
SimpleDateFormat
有时会让您避开像这样未被注意到的错误,因此,在将来某个时候出现错误时,将其追溯到格式模式字符串中使用的错误大小写将非常麻烦和昂贵。哦,当然,谢谢。出于某种原因,我认为当前的偏移量适用。@ceran不客气!我会说,认为补偿永远不会改变是很自然的(我在学习所有这些时区的东西之前也是这样做的)。但不幸的是,补偿可以随时改变。仅仅因为今天使用了一个,并不意味着它总是这样,也不能保证它永远都是一样的——我希望政治家们对此不负责任。最后一个问题:在今天执行上述代码时,UTC和伦敦以及伦敦和柏林之间有一个小时的差异。然而,UTC和CET之间的差异是两个小时。为什么呢?伦敦和柏林目前都是DST,所以伦敦的当前偏移量是
+01:00
,柏林的偏移量是
+02:00
。像
CET
这样的短名称是-这些名称通常被设置为任意默认值(在这种情况下,我相信它默认为一些中欧时区,2017年8月也有DST,所以它也使用
+02:00
UTC: 0
CET: -3600000
Europe/London: -3600000
Europe/Berlin: -3600000