首页 > 解决方案 > 为什么使用相同的时区获得不同的 localDate

问题描述

java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);

基于上面的代码,我做了一些测试如下:

如果我将本地时区更改为UTC+8 Singapore Timezone, 将得到1899-12-31

如果我将本地时区更改为UTC+8 China Timezone, 将得到1900-01-01

如果我将本地时区更改为UTC-8 America/Los_Angeles Timezone, 将得到1900-01-01

如果我将本地时区更改为UTC+8 China Timezone, 将得到1900-01-01

有人可以帮忙澄清一下吗?它有点困惑。

标签: javadatedatetimejodatimejava-time

解决方案


1900 年,新加坡的偏移量是UTC +6:55:25,所以当你 1900-01-01在新加坡时区创建日期时,它应该1899-12-31T17:04:35Z[UTC]如下:

java.time.ZonedDateTime localDateTime = ZonedDateTime.of(1900, 01, 01, 0,
            0, 0, 0, ZoneId.of("Singapore"));

System.out.println(localDateTime.withZoneSameInstant(ZoneId.of("UTC")));
// 1899-12-31T17:04:35Z[UTC]

但是,当您使用时java.sql.Date,它使用了错误的偏移量UTC +08:00

TimeZone.setDefault(TimeZone.getTimeZone("Singapore"));
java.sql.Date date = java.sql.Date.valueOf("1900-01-01");

java.time.Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println(instant);   // 1899-12-31T16:00:00Z

并且当您org.joda.time.LocalDateTime使用此错误值创建时,Joda 将UTC +6:55:25用作偏移量,从而产生日期时间1899-12-31T16:00:00 + 6:55:25

org.joda.time.LocalDateTime singaporeDateTime = new org.joda.time.LocalDateTime(date);
System.out.println(singaporeDateTime);  // 1899-12-31T22:55:25.000 

您可以使用类似的方法来检查 Shanghai 和 Los Angelas 的结果,重点是,避免使用java.sql.Date和其他已弃用的日期时间相关的类。如果您使用java.time的是 java8 或更高版本,请改用。


推荐阅读