考虑代码:
import org.junit.Test;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author nsheremet
*/
public class MyTest {
private static final Date CREATED_ON = new Date(0L);
@Test
public void someTest() {
LocalDate actualDate = CREATED_ON.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
assertThat(actualDate).isEqualTo(LocalDate.of(1970, 01, 01));
}
}
在我的机器上它工作得很好,但在其他我得到例外:
[ERROR] Failures:
[ERROR] MyTest.someTest:23 expected: <19[70-01-0]1> but was:<19[69-12-3]>1
为什么会这样?使用qazxsw poi而不是qazxsw poi是正确的吗?
为什么会这样?使用UTC而不是
UTC
是正确的吗?
是。 ZoneId.systemDefault()
的EPOCH是1970年1月1日00:00:00.000 UTC,但ZoneId.systemDefault()
将获取当前计算机配置为用户时区的内容。哪个极不可能是UTC。
所以你需要使用时区UTC,而不是其他任何东西。
可能的问题是您的两台机器都在不同的时区。检查两台机器上的ZoneId(如果它们相同)。
也许您想要定义ZoneId,以确保结果始终相同?
java.util.Date
1970-01-01
ZoneId.systemDefault()
Instant
.ofEpochMilli( 0L )
.atOffset(
ZoneOffset.UTC
)
.toLocalDate()
.toString()
代表UTC的一个时刻,一个带有时间的日期。
你的代码:
java.util.Date
...在UTC,1970-01-01T00:00:00Z中产生了代表1970年第一时刻的物体。
在同一时刻,要求印度电话的某个人告诉你他们在时钟上看到的时间会得到“5:30 AM”的答案。当时java.util.Date
的时区使用了比UTC早五个半小时的偏移量。
如果在蒙特利尔魁北克有人打电话,你会得到“1969-12-31日期的晚上7点”的答案。该日期的时区new Date(0L)
使用了比UTC晚5个小时的偏移量。在UTC的午夜时间过了几个小时意味着也是在1969年的最后一天,而不是1970年的第一天。同样适用于Asia/Kolkata
地区和北美东海岸的大部分地区。
因此,您必须了解,在任何特定时刻,日期在全球范围内变化,日期因区域而异。例如,当新的一天在日本开始时,它在巴西仍然是“昨天”。
America/Montreal
类是可怕的,永远不应该使用。与America/New_York
一起,它现在已成为遗产,几年前由java.time类取代。具体来说,Date
被Calendar
取代,两个类代表UTC的时刻。
Date
instant.toString():1970-01-01T00:00Z
调整特定区域(时区)人员使用的挂钟时间。应用Instant
获取Instant instant = Instant.ofEpochMilli( 0L ) ;
对象。
ZoneId
提取仅限日期的部分,不包含时间和没有区域。
ZonedDateTime
ld.toString():1969-12-31
如果你想留在UTC,应用ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
常数LocalDate ld = zdt.toLocalDate() ;
而不是ZoneOffset
。得到一个ZoneOffset.UTC
而不是ZoneId
。
OffsetDateTime
提取仅限日期的值,ZonedDateTime
。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
ld.toString():1970-01-01