下面的测试说明了我遇到的一些东西,将调查Date
LocalDate
转换。
对于我的设置,Java 7 和 joda-time 2.7,从 2038-3-22 左右开始,Date
到 LocalDate
和返回的转换似乎有点偏离。
对我来说,test_2038_3_21
过去了,但test_2038_3_22
没有。
这是一个已知问题吗,如果是,是否有解决方法?
package com.example;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.junit.Test;
public class TimeZoneTest {
@Test
public void test_2038_3_21() {
exerciseDate(2038, 3, 21);
}
@Test
public void test_2038_3_22() {
exerciseDate(2038, 3, 22);
}
static void exerciseDate(int year, int month, int day) {
TimeZone defaultTimeZone = TimeZone.getDefault();
String defaultUserTimezone = System.getProperty("user.timezone");
DateTimeZone defaultDateTimeZone = DateTimeZone.getDefault();
try {
for (String timeZoneId : timeZoneIds()) {
System.setProperty("user.timezone", timeZoneId);
TimeZone.setDefault(TimeZone.getTimeZone(timeZoneId));
DateTimeZone.setDefault(DateTimeZone.forID(timeZoneId));
LocalDate ld = new LocalDate(year, month, day);
DateTime dt = ld.toDateTimeAtStartOfDay();
Date d = ld.toDate();
Date dd = dt.toDate();
LocalDate ld2 = LocalDate.fromDateFields(d);
DateTime dt2 = ld2.toDateTimeAtStartOfDay();
Date d2 = ld2.toDate();
Date dd2 = dt2.toDate();
assertEquals(timeZoneId, ld, ld2);
assertEquals(timeZoneId, dt, dt2);
assertEquals(timeZoneId, d, d2);
assertEquals(timeZoneId, dd, dd2);
assertEquals(timeZoneId, d, dd);
}
} finally {
DateTimeZone.setDefault(defaultDateTimeZone);
System.setProperty("user.timezone", defaultUserTimezone);
TimeZone.setDefault(defaultTimeZone);
}
}
static List<String> timeZoneIds() {
List<String> timeZones = new ArrayList<>();
for (String timeZoneId : TimeZone.getAvailableIDs()) {
try { // only use time zones that DateTimeZone thinks are valid
DateTimeZone.forID(timeZoneId);
timeZones.add(timeZoneId);
} catch (IllegalArgumentException e) {
// ignore
}
}
return timeZones;
}
}
您可能正在遇到其中一个时区的 DST 转换。
来自LocalDate.toDate
的文档:
转换为 JDK 日期充满了复杂性,因为 JDK Date 构造函数的行为不像您在 DST 转换时所期望的那样。此方法的工作原理是先猜测,然后调整 JDK 日期,直到它具有最早的有效时刻。
请注意,未来的过渡实际上只是基于当前信息的最佳猜测。 时区规则会定期更改。 对于这么远的事情,现在和那时之间很容易发生变化。