如果我运行下列程序,它分开两个日期线的参考时间1秒分开,并比较它们:
public static void main(String[] args) throws ParseException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
Date sDt3 = sf.parse(str3);
Date sDt4 = sf.parse(str4);
long ld3 = sDt3.getTime() /1000;
long ld4 = sDt4.getTime() /1000;
System.out.println(ld4-ld3);
}
产量是:
353
為什麼 ld4-ld3 不是 1 (正如我從一秒間的差異所期望的那樣),但 353?
如果我更改日期到时间1秒后:
String str3 = "1927-12-31 23:54:08";
String str4 = "1927-12-31 23:54:09";
然后 ld4-ld3 将是 1.
Java 版本:
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)
Timezone(`TimeZone.getDefault()`):
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]
Locale(Locale.getDefault()): zh_CN
首頁 〉外文書 〉文學 〉文學 〉Stop Press! History Changes
原始问题将不再表现出完全相同的行为,如果重建与2013a版本的TZDB. 在2013a,结果将是358秒,过渡时间为23:54:03而不是23:54:08.
我只注意到这一点,因为我在Noda Time中收集了类似的问题,以单位测试的形式......测试现在已经改变了,但它只是为了证明 - 甚至历史数据也不安全。
import java.util.TimeZone;
public class Test {
public static void main(String[] args) throws Exception {
long startOf1900Utc = -2208988800000L;
for (String id : TimeZone.getAvailableIDs()) {
TimeZone zone = TimeZone.getTimeZone(id);
if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
System.out.println(id);
}
}
}
}
上面的代码不会在我的Windows机器上产生任何输出。 因此,任何时间区,在1900年初除了它的标准一个没有任何折扣将计算为过渡。 TZDB本身有某些数据返回之前,并且不依赖任何“固定”标准时间的想法(这是什么 getRawOffset假设是一个有效的概念),所以其他图书馆不需要引入这个人工时间。
正如其他人所解释的那样,有时间停滞在那里. 在亚洲/上海,有2个可能的时间区差距为1927-12-31 23:54:08 但只有1个差距为1927-12-31 23:54:07. 因此,取决于使用的差距,有1秒差距或5分钟和53秒差距。
这种轻微的交换,而不是我们习惯的一个小时的日光节约(夏季时间),隐藏了这个问题一点。
在 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());
此外,这两个外套是相同的:
// 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();
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
您可以检查过渡是否是一个过渡,如果有超过一个有效的折扣为该日期/时间或一个差距,如果该日期/时间不适用于该区域ID - 使用 isOverlap() 和 isGap() 方法在 zot4 。
出口 LC_ALL=C TZ=UTC 设置系统时钟到 UTC 永远不会使用定位实施,除非绝对必要(即仅显示)
对于Java Community Process的成员,我建议:
做定位的方法,而不是默认,但要求用户明确要求定位. 使用 UTF-8/UTC 作为固定默认,而不是因为这只是今天的默认。
我指的是,来吧,全球静态变量不是一个反OO模式吗?没有别的东西是那些由某些基本的环境变量给予的突破性缺陷......。
正如其他人所说,这是上海1927年的时间变化。
在上海,当地标准时间是23:54:07,但然后在5分钟52秒后,它转到下一天在00:00,然后当地标准时间转到23:54:08. 因此,这就是为什么两次之间的差异是343秒,而不是1秒,你会预料到的。
日光节约时间开始时,时间前进1小时,但过了一会儿,日光节约时间结束,它回到标准时间区1小时,所以有时在比较时间在美国,差异约为3600秒而不是1秒。
但是,关于这两次的变化有什么不同,后者不断变化,前者只是一个变化,它没有改变或再改变相同的数量。
最好使用UTC,除非需要使用非UTC时间,如在显示中。