JSR 310 :: System.currentTimeMillis()vs Instant.toEpochMilli():: TimeZone

时间:2015-10-06 16:51:16

标签: java datetime timezone java-8 java-time

请您详细说明如何获得默认系统时区和给定时区的正确纪元时间(以毫秒为单位)。

鉴于

1。 TimeZone:GMT + 3

2。以下代码段:

import java.time.*;

public class Main {        
    public static void main(String[] args) {
        System.out.println(LocalDateTime
            .now()
            .atZone(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli()
        );
        System.out.println(LocalDateTime
            .now()
            .atZone(ZoneOffset.of("+3"))
            .toInstant()
            .toEpochMilli()
        );
        System.out.println(System.currentTimeMillis());
    }
}

3。输出:

1444158955508
1444148155508
1444148155508

4。 System.currentTimeMillis()的JavaDoc,它告诉返回的值当前时间与1970年1月1日午夜时间之间的差值(以毫秒为单位)。

那么,为什么

  1. LocalDateTime GMT+3的输出与System.currentTimeMillis()的输出相同,但System.currentTimeMillis()提及UTC的文档?
  2. LocalDateTime UTC的输出与System.currentTimeMillis()不同,尽管System.currentTimeMillis()的文档提及UTC

3 个答案:

答案 0 :(得分:32)

System.currentTimeMillis()Instant.toEpochMilli()都返回自Unix纪元以来的毫秒数。虽然Unix纪元通常表示为“1970年1月1日午夜,UTC”,但它并非“在”任何特定时区。但是瞬间只是一个瞬间,并且与您所处的时区相同 - 但它会反映当地时间的不同。

LocalDateTime.atZone(UTC)的输出不同,因为您说“获取本地日期和时间,并将其转换为瞬间,就像它在UTC时区” - 甚至虽然当你创建了LocalDateTime时,你在UTC + 3时区中隐含地这样做了......这就是为什么它是“错误的”。

LocalDateTime.now()获取系统默认时区中的本地日期和时间。因此,如果您的时区是UTC + 3,当前时刻是2015-10-06T16:57:00Z,那么LocalDateTime.now()将返回.2015-10-06T19:57:00。我们称之为localNow ...

所以localNow.atZone(ZoneOffset.of("+3"))将返回ZonedDateTime代表2015-10-06T19:57:00 + 03 - 换句话说,相同的本地日期/时间,但“知道”提前3小时UTC ...所以toInstant()将返回代表2015-10-06T16:57:00Z的Instant。太棒了 - 我们仍然有当前的日期/时间。

localNow.atZone(ZoneOffset.UTC)将返回代表2015-10-06T19:57:00Z的ZonedDateTime - 换句话说,相同的本地日期/时间,但“认为”它已经在UTC中。 。toInstant()将返回代表2015-10-06T19:57:00Z的Instant ..这不是当前时间(三小时内)。

答案 1 :(得分:1)

简短版本

无法计算LocalDateTime -> Instant,需要指定时区。 使用时区,您将获得ZonedDateTime并可以计算ZonedDateTime -> Instant

Instant == System.currentTimeMillis(),如果ZonedDateTime的时区等于系统默认时区。

长版

LocalDateTime是时钟上的时间(加上日期信息)。如果您不告诉我们您所在的时区,那还不够。东京的13:00点与巴黎的13:00点是同一时间。

将时区添加到LocalDateTime后,您将获得一个ZonedDateTime,我们可以知道您实际在哪一个即时时间。例如。您是在东京还是巴黎的13:00?

要获取正确的Instant,ZonedDateTime的时区必须正确。如果东京时间是13:00,但您声称自己是巴黎的13:00,则会收到错误的“ Instant”(即时)。

LocalDateTime

  

如果没有其他信息(例如偏移量或时区),则无法在时间轴上表示时刻。

ZonedDateTime

  

此类处理从LocalDateTime的本地时间线到Instant的即时时间线的转换。两条时间线之间的差异是相对于UTC /格林威治的偏移量,由ZoneOffset表示。

要获取Instant,您需要先将LocalDateTime转换为ZonedDateTime。如果您正确地做到了这一点(通过指出正确的时区),则Instant将同意System.currentTimeMillis()。

System.currentTimeMillis()

  

当前时间与UTC 1970年1月1日午夜之间的差值(以毫秒为单位)。

  1. GMT + 3上LocalDateTime的输出与System.currentTimeMillis()的输出相同,尽管System.currentTimeMillis()的文档中提到了UTC?

如果您的时区是格林尼治标准时间+3,那么ZonedDateTime.toInstant()将为您提供正确的即时消息,因此同意System.currentTimeMillis()

  1. 在UTC上LocalDateTime的输出与System.currentTimeMillis()不同,尽管System.currentTimeMillis()的文档中提到了UTC?

如果您的时区不是世界标准时间(UTC),那么ZonedDateTime.toInstant()将为您提供不正确的即时信息。

答案 2 :(得分:0)

System.out.println("Output 1 : " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("Output 2 : " + System.currentTimeMillis());

输出1:1576047664910

输出2:1576047664911