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

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

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

特定

1. TimeZone:GMT + 3

2.以下代码段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.输出:

1
2
3
1444158955508
1444148155508
1444148155508

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

所以为什么

  • LocalDateTimeGMT+3的输出与System.currentTimeMillis()的输出相同,但System.currentTimeMillis()的文档提到UTC
  • LocalDateTime的输出UTCSystem.currentTimeMillis()不同,尽管System.currentTimeMillis()的文档提到UTC

  • 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"))将返回代表2015-10-06T19:57:00 + 03的ZonedDateTime - 换句话说,相同的本地日期/时间,但"知道"它比UTC提前3小时...所以< x10>将返回代表2015-10-06T16:57:00Z的Instant。太棒了 - 我们还有当前的日期/时间。

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


    精简版:

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

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

    长版:

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

    将时区添加到LocalDateTime后,您将获得ZonedDateTime,我们可以知道您实际上是在哪个瞬间。例如。你在东京或巴黎的13点吗?

    要获得正确的Instant,ZonedDateTime的时区需要正确。如果是东京时间下午1点,但你声称自己是巴黎的13点,那么你将得到一个错误的瞬间。

    LocalDateTime:

    It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

    ZonedDateTime:

    This class handles conversion from the local time-line of LocalDateTime to the instant time-line of Instant. The difference between the two time-lines is the offset from UTC/Greenwich, represented by a ZoneOffset.

    要获得Instant,您需要先将LocalDateTime转换为ZonedDateTime。如果您正确执行此操作(通过声明正确的时区),您的Instant将同意System.currentTimeMillis()。

    System.currentTimeMillis的():

    the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.

  • GMT + 3的LocalDateTime的输出与System.currentTimeMillis()的输出相同,尽管System.currentTimeMillis()的文档提到了UTC?
  • 如果您的时区是GMT + 3,那么ZonedDateTime.toInstant()将为您提供正确的Instant,因此同意System.currentTimeMillis()

  • UTC的LocalDateTime输出与System.currentTimeMillis()不同,尽管System.currentTimeMillis()的文档提到了UTC?
  • 如果您的时区不是UTC,那么ZonedDateTime.toInstant()会给您一个不正确的Instant。