fei*_*fei 6 java datetime date
TimeZone.setDefault(TimeZone.getTimeZone("BET"));
Locale.setDefault(Locale.ENGLISH);
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS zzzz");
Date d0 = sdf1.parse("2037-10-17 23:00:00.000");
Date d1 = sdf1.parse("2037-10-17 23:00:00.001");
Date d2 = sdf1.parse("2037-10-17 23:59:59.999");
Date d3 = sdf1.parse("2037-10-18 00:00:00.000");
Date d4 = sdf1.parse("2037-10-18 00:00:00.001");
Date d5 = sdf1.parse("2037-10-18 00:59:59.999");
Date d6 = sdf1.parse("2037-10-18 01:00:00.000");
Date d7 = sdf1.parse("2037-10-18 01:00:00.001");
Date d8 = sdf1.parse("2037-10-18 01:59:59.999");
Date d9 = sdf1.parse("2037-10-18 02:00:00.000");
System.out.println(sdf2.format(d0) + "(" + d0.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d0) + ", offset: " + TimeZone.getDefault().getOffset(d0.getTime()));
System.out.println(sdf2.format(d1) + "(" + d1.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d1) + ", offset: " + TimeZone.getDefault().getOffset(d1.getTime()));
System.out.println(sdf2.format(d2) + "(" + d2.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d2) + ", offset: " + TimeZone.getDefault().getOffset(d2.getTime()));
System.out.println(sdf2.format(d3) + "(" + d3.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d3) + ", offset: " + TimeZone.getDefault().getOffset(d3.getTime()));
System.out.println(sdf2.format(d4) + "(" + d4.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d4) + ", offset: " + TimeZone.getDefault().getOffset(d4.getTime()));
System.out.println(sdf2.format(d5) + "(" + d5.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d5) + ", offset: " + TimeZone.getDefault().getOffset(d5.getTime()));
System.out.println(sdf2.format(d6) + "(" + d6.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d6) + ", offset: " + TimeZone.getDefault().getOffset(d6.getTime()));
System.out.println(sdf2.format(d7) + "(" + d7.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d7) + ", offset: " + TimeZone.getDefault().getOffset(d7.getTime()));
System.out.println(sdf2.format(d8) + "(" + d8.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d8) + ", offset: " + TimeZone.getDefault().getOffset(d8.getTime()));
System.out.println(sdf2.format(d9) + "(" + d9.getTime() + "), dst: " + TimeZone.getDefault().inDaylightTime(d9) + ", offset: " + TimeZone.getDefault().getOffset(d9.getTime()));
Run Code Online (Sandbox Code Playgroud)
输出
2037-10-17 23:00:00.000 Brasilia Time(2139444000000), dst: false, offset: -10800000
2037-10-17 23:00:00.001 Brasilia Time(2139444000001), dst: false, offset: -10800000
2037-10-17 23:59:59.999 Brasilia Time(2139447599999), dst: false, offset: -10800000
2037-10-18 01:00:00.000 Brasilia Summer Time(2139447600000), dst: true, offset: -7200000
2037-10-18 00:00:00.001 Brasilia Time(2139447600001), dst: true, offset: -10800000
2037-10-18 00:59:59.999 Brasilia Time(2139451199999), dst: true, offset: -10800000
2037-10-18 01:00:00.000 Brasilia Summer Time(2139447600000), dst: true, offset: -7200000
2037-10-18 00:00:00.001 Brasilia Time(2139447600001), dst: true, offset: -10800000
2037-10-18 00:59:59.999 Brasilia Time(2139451199999), dst: true, offset: -10800000
2037-10-18 02:00:00.000 Brasilia Summer Time(2139451200000), dst: true, offset: -7200000
Run Code Online (Sandbox Code Playgroud)
此代码打印出"2037-10-18 00:00:000巴西利亚时间"的日期时间,结果显示"2037-10-18 00:00:000巴西利亚时间"应为"2037-10- 18 01:00:00.000巴西利亚夏令时"这意味着巴西利亚在那个时刻进入夏季.
我的问题是为什么在"2037-10-18 00:00:00.001巴西利亚时间"和"2037-10-18 00:59:59.999巴西利亚时间"之间仍然使用标准时间偏移的时区偏移.这是JDK时区数据的错误还是这个时区实际上是这样工作的.
我的代码使用offset来决定两个日期之间是否存在dst转换.显然"2037-10-18 01:00:00.000巴西利亚夏令时"和"2037-10-18 00:59:59.999巴西利亚时间"这两个日期在这里不起作用.
我可以更改为使用"TimeZone.getDefault().inDaylightTime(Date date)"来判断是否存在转换,但我仍然想知道它是否是JDK的错误.
我尝试使用调试器单步执行代码,这似乎是时区和开关本身的问题:BRT 到 BRST 在午夜从 00:00:00 切换到 01:00:00,这意味着中间的那一小时实际上不存在。
从我的调试来看,问题似乎GregorianCalendar#computeTime()特别出在以下行中:
millis -= zoneOffsets[0] + zoneOffsets[1];
Run Code Online (Sandbox Code Playgroud)
该行之前millis是自纪元以来的时间,它是根据解析的日期计算出来的,并且对于00:00:00(213946800000) 和01:00:00(2139440400000) 来说是不同的。在这两种情况下zoneOffsets[0]都是-10800000,这是相对于 UTC 的原始偏移量。
区别在于zoneOffsets[1]: for 00:00:00it 为 0,而 for 01:00:00is 为 3600000,即 1 小时。其原因似乎是一个内部调用,对于(夏令时之前)inDaylightTime( new Date(millis) )返回 false ,但对于(夏令时第一个小时)返回 true。因此,最终时间将是相同的,因为您总是添加 10800000 毫利斯,但从较高值中减去 3600000 毫利斯,即高出 3600000 毫利斯:)00:00:0001:00:00
最后你得到了Date同样的毫秒时间。
再次格式化日期时,格式化程序似乎会根据时区检查毫秒时间,并且每次对应时00:00:00,000 - 59:59:59,999,即可能位于两个时区的时间将被假定为dstOffset0 而不是 3600000,因此时区不同被打印。
编辑:比较时,01:00:00.000似乎01:00:00.001可能存在一个错误,ZoneInfo.getOffsets(time, offsets, type)前者返回 360000 的 dst 偏移量,后者返回 0 的 dst 偏移量,而在格式化程序内填充日历字段时,两者都将假定 dst。
编辑2:当更改解析器格式以接受时区快捷方式时,您可以观察到相同的行为,即00:00:00.000 BRT和01:00:00.000 BRST被解析为 2139447600000 并再次格式化为01:00:00.000 BRSTwhile00:00:00.001 BRT并被01:00:00.001 BRST解析为 2139447600001 并格式化为00:00:00.001 BRT- 这本身是正确的。
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |