JAVA日期转换错误_java – jdk8日期转换中的错误?

不同的结果源于切换到夏季时间的不匹配,从2038年的日期开始.您可以使用以下代码可视化差异:

// for reproducible results

System.setProperty("user.timezone", "Europe/Berlin");

LocalDate[] dates = {LocalDate.of(2037, 3, 29), LocalDate.of(2038, 3, 28)};

LocalTime[] time = { LocalTime.of(0, 59, 59), LocalTime.of(1, 00, 01),

LocalTime.of(1, 59, 59), LocalTime.of(2, 00, 01) };

for(LocalDate localDate : dates) {

for(LocalTime localTime1 : time) {

ZonedDateTime zoned = LocalDateTime.of(localDate, localTime1)

.atZone(ZoneId.of("UTC"))

.withZoneSameInstant(ZoneId.systemDefault());

System.out.println(zoned);

System.out.println(new java.util.Date(zoned.toEpochSecond()*1000));

}

System.out.println();

}

将打印:

2037-03-29T01:59:59+01:00[Europe/Berlin]

Sun Mar 29 01:59:59 CET 2037

2037-03-29T03:00:01+02:00[Europe/Berlin]

Sun Mar 29 03:00:01 CEST 2037

2037-03-29T03:59:59+02:00[Europe/Berlin]

Sun Mar 29 03:59:59 CEST 2037

2037-03-29T04:00:01+02:00[Europe/Berlin]

Sun Mar 29 04:00:01 CEST 2037

2038-03-28T01:59:59+01:00[Europe/Berlin]

Sun Mar 28 01:59:59 CET 2038

2038-03-28T03:00:01+02:00[Europe/Berlin]

Sun Mar 28 02:00:01 CET 2038

2038-03-28T03:59:59+02:00[Europe/Berlin]

Sun Mar 28 02:59:59 CET 2038

2038-03-28T04:00:01+02:00[Europe/Berlin]

Sun Mar 28 04:00:01 CEST 2038

我们可以看到,两种实现都同意在2037年切换到夏令时的瞬间,而java.util.*实现在2038年后一小时后切换.

我们可以验证这种情况发生了:

long l1 = LocalDateTime.of(LocalDate.of(2037, 3, 29), LocalTime.of(1, 00, 01))

.atZone(ZoneId.of("UTC")).toInstant().getEpochSecond()*1000;

long l2 = LocalDateTime.of(LocalDate.of(2038, 3, 28), LocalTime.of(1, 00, 01))

.atZone(ZoneId.of("UTC")).toInstant().getEpochSecond()*1000;

TimeZone zone=TimeZone.getTimeZone("Europe/Berlin");

Field table=zone.getClass().getDeclaredField("transitions");

table.setAccessible(true);

System.out.println("table length="+((long[])table.get(zone)).length);

Method getTransitionIndex = zone.getClass()

.getDeclaredMethod("getTransitionIndex", long.class, int.class);

getTransitionIndex.setAccessible(true);

final Integer UTC_TIME = 0;

int indexFor2037 = (Integer)getTransitionIndex.invoke(zone, l1, UTC_TIME);

System.out.println("index for 2037="+indexFor2037);

int indexFor2038 = (Integer)getTransitionIndex.invoke(zone, l2, UTC_TIME);

System.out.println("index for 2038="+indexFor2038);

打印在我的系统上:

table length=143

index for 2037=141

index for 2038=143

我不知道有什么计划在2038年改变夏令时切换,所以我认为java.time实现是正确的.很明显,任何基于硬编码值有限表的实现都有一个自然的局限性……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值