如何以毫秒为单位返回 LocalDate.now()?
Posted
技术标签:
【中文标题】如何以毫秒为单位返回 LocalDate.now()?【英文标题】:How can I return LocalDate.now() in milliseconds? 【发布时间】:2018-01-30 11:44:01 【问题描述】:我现在创建日期:
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()
?
【问题讨论】:
日期怎么会有毫秒?毫秒是时间戳的一部分,而不是日期 @Jens localDateTime.atZone(gmt).toEpochSecond() 返回 1503403331 (18.01.70) 到 你在说什么LocalDate
或LocalDateTime
?您要求 LocalDate 并以 LocalDateTime
为例。
即时调用toEpochSecond(),调用toInstant().toEpochMilli()
@JB Nizet 谢谢!正是需要的!
【参考方案1】:
按照@JB Nizet's comment 的建议,拨打toInstant().toEpochMilli()
是正确的答案,但您必须注意有关使用当地日期的一些小细节。
但在此之前,还有一些其他的小细节:
您可以使用内置常量ZoneOffset.UTC
,而不是ZoneId.of("GMT")
。它们是等价的,但如果 API 已经提供了完全相同的对象,则无需创建额外的冗余对象。
您可以直接调用LocalDate.now()
,而不是先调用LocalDateTime.now()
,然后再调用.toLocalDate()
- 它们是等价的。
现在是棘手的细节:当您调用 now()
方法时(对于 LocalDateTime
或 LocalDate
),它使用 JVM 的默认时区来获取当前日期的值,并且该值可能会有所不同,具体取决于在 JVM 中配置的时区。
在我使用的JVM中,默认时区是America/Sao_Paulo
,这里的当地时间是09:37 AM。所以LocalDate.now()
返回2017-08-22
(2017 年 8 月 22th)。
但如果我将默认时区更改为Pacific/Kiritimati
,它会返回2017-08-23
。那是因为在 Kiritimati,现在已经是 2017 年 8 月 23th(我写这篇文章的那一刻,那里的当地时间是 02:37 AM)。
所以,如果我在默认时区为 Pacific/Kiritimati
时运行此代码:
LocalDate dtNow = LocalDate.now(); // 2017-08-23
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());
输出是:
1503446400000
相当于 UTC 时间 2017 年 8 月 23th 午夜。
如果我在默认时区为America/Sao_Paulo
时运行相同的代码,结果将是:
1503360000000
相当于 2017 年 8 月 22th UTC 午夜。
使用now()
使您的代码依赖于JVM 的默认时区。而这个配置can be changed without notice, even at runtime,让你的代码在发生这种变化时返回不同的结果。
而且您不需要这种极端情况(例如有人将 JVM 错误配置为“非常远”的时区)。例如,在America/Sao_Paulo
时区,如果我在晚上11 点 运行代码,LocalDate
将返回 August 22th,但 UTC 的当前日期已经是 8 月 23th。这是因为圣保罗的晚上 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());
输出是:
1503360000000
相当于 2017 年 8 月 22th UTC 午夜。
另一种选择是将时区传递给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());
【讨论】:
以上是关于如何以毫秒为单位返回 LocalDate.now()?的主要内容,如果未能解决你的问题,请参考以下文章
如何以毫秒为单位获得两个 QDateTimes 之间的差异?
在 SQL Server 2008R2 上以毫秒为单位返回 DATEDIFF