为什么使用相同的时区获取不同的 localDate

Hav*_*Lin 2 java datetime date jodatime java-time

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

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

  • 问题 #1 为什么我会得到具有相同时区的不同 localDate 对象?

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

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

  • 问题 #2 为什么我在不同的时区得到相同的时间?

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

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

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

孙兴斌*_*孙兴斌 5

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]
Run Code Online (Sandbox Code Playgroud)

但是,当您使用时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
Run Code Online (Sandbox Code Playgroud)

当你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 
Run Code Online (Sandbox Code Playgroud)

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