我现在创建日期:
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()
?
答案 0 :(得分:15)
按照@JB Nizet's comment的建议调用toInstant().toEpochMilli()
是正确的答案,但有一些关于使用您必须注意的本地日期的细节问题。
但在此之前,还有其他一些细节:
ZoneId.of("GMT")
代替ZoneOffset.UTC
。它们是等价的,但如果API已经提供了完全相同的东西,则无需创建额外的冗余对象。LocalDateTime.now()
,而不是拨打.toLocalDate()
然后再调用LocalDate.now()
,而是等同。现在棘手的细节:当你调用now()
方法(对于LocalDateTime
或LocalDate
)时,它使用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());