如何以毫秒为单位返回LocalDate.now()?

时间:2017-08-22 09:09:04

标签: java-8 timestamp java-time localdate

我现在创建日期:

ZoneId gmt = ZoneId.of("GMT");
LocalDateTime localDateTime = LocalDateTime.now();
LocalDate localDateNow = localDateTime.toLocalDate();

然后我希望以毫秒为单位返回此日期:

localDateNow.atStartOfDay(gmt) - 22.08.2017
localDateNow.atStartOfDay(gmt).toEpochSecond(); - 1503360000 (18.01.70)

如何以毫秒为单位返回LocalDate.now()

1 个答案:

答案 0 :(得分:15)

按照@JB Nizet's comment的建议调用toInstant().toEpochMilli()是正确的答案,但有一些关于使用您必须注意的本地日期的细节问题。

但在此之前,还有其他一些细节:

  • 您可以使用内置常量ZoneId.of("GMT")代替ZoneOffset.UTC。它们是等价的,但如果API已经提供了完全相同的东西,则无需创建额外的冗余对象。
  • 您可以直接致电LocalDateTime.now(),而不是拨打.toLocalDate()然后再调用LocalDate.now(),而是等同。

现在棘手的细节:当你调用now()方法(对于LocalDateTimeLocalDate)时,它使用JVM的默认时区来获取当前日期的值,并且此值可能会有所不同,具体取决于JVM中配置的时区。

在我正在使用的JVM中,默认时区为America/Sao_Paulo,此处的本地时间为 09:37 AM 。因此LocalDate.now()会返回2017-08-22(8月 22 th 2017)。

但如果我将默认时区更改为Pacific/Kiritimati,则会返回2017-08-23。那是因为在Kiritimati,现在已经是八月 23 th 2017(那里的当地时间,在我写这篇文章时, 02:37 AM < /强>)。

因此,如果我在默认时区为Pacific/Kiritimati时运行此代码:

LocalDate dtNow = LocalDate.now(); // 2017-08-23
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());

输出结果为:

  

1503446400000

相当于8月 23 th 2017年午夜的UTC。

如果我在默认时区为America/Sao_Paulo时运行相同的代码,结果将为:

  

15033.6亿

相当于2017年8月 22 th 的午夜时间。

使用now()使您的代码取决于JVM的默认时区。此配置can be changed without notice, even at runtime,使您的代码在发生此类更改时返回不同的结果。

并且您不需要这样的极端情况(就像有人将JVM错误配置为“非常远”的时区)。在我的情况下,例如,在America/Sao_Paulo时区,如果我在晚上11点运行代码,LocalDate将返回八月 22 th ,但UTC中的当前日期已经是8月 23 th 。那是因为圣保罗的晚上11点与UTC的次日的凌晨2点相同:

// August 22th 2017, at 11 PM in Sao Paulo
ZonedDateTime z = ZonedDateTime.of(2017, 8, 22, 23, 0, 0, 0, ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2017-08-22T23:00-03:00[America/Sao_Paulo]
System.out.println(z.toInstant()); // 2017-08-23T02:00:00Z (in UTC is already August 23th)

所以使用LocalDate.now()保证我将始终拥有 UTC当前日期

如果您希望当前日期为UTC (无论JVM默认时区如何)并将时间设置为午夜,最好使用ZonedDateTime

// current date in UTC, no matter what the JVM default timezone is 
ZonedDateTime zdtNow = ZonedDateTime.now(ZoneOffset.UTC);
// set time to midnight and get the epochMilli
System.out.println(zdtNow.with(LocalTime.MIDNIGHT).toInstant().toEpochMilli());

输出结果为:

  

15033.6亿

相当于2017年8月 22 th 的午夜时间。

另一种方法是将时区传递给LocalDate.now,这样它就可以获得指定区域上当前日期的正确值:

// current date in UTC, no matter what the JVM default timezone is 
LocalDate dtNowUtc = LocalDate.now(ZoneOffset.UTC);
// set time to midnight and get the epochMilli
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());