我很遗憾地说,但是时间的不连续性已经发生了变化
JDK 6 两年前,在 JDK 7 就在最近 更新25 。
要学习的课程:不惜一切代价避免非UTC时间,除了显示。
您可以使用以下代码,而不是转换每个日期
long difference = (sDt4.getTime() - sDt3.getTime()) / 1000; System.out.println(difference);
并看到结果是:
1
在递增时间时,您应该转换回UTC然后加或减。仅使用当地时间进行显示。
通过这种方式,您可以在几小时或几分钟发生两次的任何时段走过。
如果转换为UTC,请添加每秒,然后转换为本地时间进行显示。你会经过晚上11:54:08。 LMT - 下午11:59:59 LMT然后是晚上11:54:08 CST - 下午11:59:59 CST。
恕我直言,无处不在, 含蓄 Java中的本地化是其最大的设计缺陷。它可能适用于用户界面,但坦率地说,现在谁真正使用Java作为用户界面,除了一些IDE,你基本上可以忽略本地化,因为程序员并不是它的目标受众。您可以通过以下方式修复它(特别是在Linux服务器上):
到了 Java社区流程 我推荐的成员:
我的意思是,来吧,不是全局静态变量是反OO模式吗?没有其他东西是由一些基本的环境变量给出的那些普遍的默认值.......
你遇到了一个 当地时间不连续 :
当地标准时间即将到达星期日,1928年1月1日, 00:00:00时钟倒退0:05:52至星期六,31。 1927年12月,当地标准时间23:54:08代替
这并不是特别奇怪,并且由于政治或行政行为导致时区被切换或改变,因此在任何时候都发生过这种情况。
这种陌生感的道德是:
正如其他人所解释的那样,那里有一段时间不连续。有两种可能的时区偏移 1927-12-31 23:54:08 在 Asia/Shanghai ,但只有一个偏移 1927-12-31 23:54:07 。因此,根据使用的偏移量,存在一秒差异或5分53秒差异。
1927-12-31 23:54:08
Asia/Shanghai
1927-12-31 23:54:07
这种轻微的偏移转移,而不是我们习惯的通常的一小时夏令时(夏令时),有点模糊了问题。
请注意,时区数据库的2013a更新在几秒钟之前移动了此不连续性,但效果仍然可以观察到。
新的 java.time Java 8上的包使用更清楚地看到它,并提供处理它的工具。鉴于:
java.time
DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder(); dtfb.append(DateTimeFormatter.ISO_LOCAL_DATE); dtfb.appendLiteral(' '); dtfb.append(DateTimeFormatter.ISO_LOCAL_TIME); DateTimeFormatter dtf = dtfb.toFormatter(); ZoneId shanghai = ZoneId.of("Asia/Shanghai"); String str3 = "1927-12-31 23:54:07"; String str4 = "1927-12-31 23:54:08"; ZonedDateTime zdt3 = LocalDateTime.parse(str3, dtf).atZone(shanghai); ZonedDateTime zdt4 = LocalDateTime.parse(str4, dtf).atZone(shanghai); Duration durationAtEarlierOffset = Duration.between(zdt3.withEarlierOffsetAtOverlap(), zdt4.withEarlierOffsetAtOverlap()); Duration durationAtLaterOffset = Duration.between(zdt3.withLaterOffsetAtOverlap(), zdt4.withLaterOffsetAtOverlap());
然后 durationAtEarlierOffset 将是一秒钟,而 durationAtLaterOffset 将是五分53秒。
durationAtEarlierOffset
durationAtLaterOffset
此外,这两个偏移是相同的:
// Both have offsets +08:05:52 ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset(); ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
但这两者是不同的:
// +08:05:52 ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset(); // +08:00 ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
您可以看到比较相同的问题 1927-12-31 23:59:59 同 1928-01-01 00:00:00 但是,在这种情况下,它是较早的偏移产生较长的偏差,而较早的日期有两个可能的偏移。
1927-12-31 23:59:59
1928-01-01 00:00:00
另一种方法是检查是否正在进行转换。我们可以这样做:
// Null ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime); // An overlap transition ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
您可以检查转换是否是重叠 - 在这种情况下,该日期/时间有多个有效偏移量 - 或者是间隙 - 在这种情况下,日期/时间对于该区域ID无效 - 通过使用 isOverlap() 和 isGap() 方法 zot4 。
isOverlap()
isGap()
zot4
我希望这有助于人们在Java 8广泛使用后处理这类问题,或者使用采用JSR 310 backport的Java 7的人。
正如其他人所提到的,这是1927年在上海的时间变化。
基本上,那 23:54:07 在上海,当地的标准时间,过了一会儿,它转向第二天 00:00:00 。但后来又转回了 23:54:08 为当地标准时间。所以,这就是为什么差异是343秒而不是1秒。
23:54:07
00:00:00
23:54:08
这也可以搞砸美国等其他地方。在美国,他们有夏令时。当夏令时开始时,时间前进1小时。但过了一段时间夏令时结束后,它会向后退一小时回到标准时区。因此,有时在比较美国的时间差异时 3600 秒不是1秒。
3600
的 最好在时间不变的情况下使用UTC,除非在显示时需要使用非UTC时间。 强>