gpt4 book ai didi

java - 在 Java 中处理日期和时间的不一致

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:45:07 26 4
gpt4 key购买 nike

我注意到 java 中日期和时间的奇怪行为。我有以下代码:

public class TestDateTime {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Helsinki"));

Calendar calendar = GregorianCalendar.getInstance();

assert(calendar.getTimeZone().equals(TimeZone.getDefault()));
//Set 1899-12-30T23:00:00
calendar.set(1899,11,30,23,0,0);
calendar.set(Calendar.MILLISECOND,0);

long timeInMillis = calendar.getTimeInMillis();
java.util.Date calendarDateTime = new java.util.Date(timeInMillis);

LocalDateTime localDateTime = LocalDateTime.ofInstant(ofEpochMilli(timeInMillis), ZoneId.systemDefault());
System.out.println("Time in millis: " + timeInMillis);
System.out.println("Date: " + calendarDateTime.toString());
System.out.println("Local DateTime: " + localDateTime.toString());
}
}

输出是:

Time in millis: -2209086000000
Date: Sat Dec 30 23:00:00 EET 1899
Local DateTime: 1899-12-30T22:39:49

timeInMillis 必须包含从 1970-01-01T00:00:00Z 传递的毫秒数。Date 类的实例存储从 1970-01-01T00:00:00Z 传递的毫秒数。Date.toString() 方法返回默认时区的本地日期和时间。

因此 Date.toString()LocalDateTime.toString() 必须返回相同的日期和时间,但我们看到了差异(超过 20 分钟)。

这是 java 的错误,还是我在 Java 中错误地使用了日期和时间?

最佳答案

这是芬兰时间变化造成的怪异现象,参见Clock Changes in Helsinki, Finland (Helsingfors) in 1921 :

May 1, 1921 - Time Zone Change (HMT → EET)

When local standard time was about to reachSunday, May 1, 1921, 12:00:00 midnight clocks were turned forward 0:20:11 hours toSunday, May 1, 1921, 12:20:11 am local standard time instead

那 20 分 11 秒似乎就是您所观察到的。

作为Jim Garrison said in his answer , LocalDateTime 正确处理了它,而 Calendar 则没有。

实际上,似乎旧的 TimeZone 得到的偏移量是错误的,而新的 ZoneId 得到的是正确的,如以下测试代码所示:

public static void main(String[] args) {
compare(1800, 1, 1, 0, 0, 0);
compare(1899,12,31, 23,59,59);
compare(1900, 1, 1, 0, 0, 0);
compare(1900,12,30, 23, 0, 0);
compare(1921, 4,30, 0, 0, 0);
compare(1921, 5, 1, 0, 0, 0);
compare(1921, 5, 2, 0, 0, 0);
}
private static void compare(int year, int month, int day, int hour, int minute, int second) {
Calendar calendar = new GregorianCalendar();
calendar.clear();
calendar.setTimeZone(TimeZone.getTimeZone("Europe/Helsinki"));
calendar.set(year, month-1, day, hour, minute, second);
Date date = calendar.getTime();

ZonedDateTime zdt = ZonedDateTime.of(year, month, day, hour, minute, second, 0, ZoneId.of("Europe/Helsinki"));

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z XXX");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/Helsinki"));
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss z XXX");

System.out.printf("%04d-%02d-%02d %02d:%02d:%02d %s = %d %s = %d %d%n",
year, month, day, hour, minute, second,
sdf.format(date), date.getTime(),
dtf.format(zdt), zdt.toInstant().toEpochMilli(),
date.getTime() - zdt.toInstant().toEpochMilli());
}

输出

1800-01-01 00:00:00   1800-01-01 00:00:00 EET +02:00 = -5364669600000   1800-01-01 00:00:00 EET +01:39 = -5364668389000   -1211000
1899-12-31 23:59:59 1899-12-31 23:59:59 EET +02:00 = -2208996001000 1899-12-31 23:59:59 EET +01:39 = -2208994790000 -1211000
1900-01-01 00:00:00 1900-01-01 00:00:00 EET +02:00 = -2208996000000 1900-01-01 00:00:00 EET +01:39 = -2208994789000 -1211000
1900-12-30 23:00:00 1900-12-30 23:00:00 EET +01:39 = -2177548789000 1900-12-30 23:00:00 EET +01:39 = -2177548789000 0
1921-04-30 00:00:00 1921-04-30 00:00:00 EET +01:39 = -1536025189000 1921-04-30 00:00:00 EET +01:39 = -1536025189000 0
1921-05-01 00:00:00 1921-05-01 00:20:11 EET +02:00 = -1535938789000 1921-05-01 00:20:11 EET +02:00 = -1535938789000 0
1921-05-02 00:00:00 1921-05-02 00:00:00 EET +02:00 = -1535853600000 1921-05-02 00:00:00 EET +02:00 = -1535853600000 0

关于java - 在 Java 中处理日期和时间的不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42865515/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com