如何以毫秒为单位返回 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) 到 你在说什么LocalDateLocalDateTime?您要求 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() 方法时(对于 LocalDateTimeLocalDate),它使用 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()?的主要内容,如果未能解决你的问题,请参考以下文章

localdate如何返回成字符串前端

如何以毫秒为单位获得两个 QDateTimes 之间的差异?

如何在ssis包中捕获包的启动时间,以毫秒为单位

在 SQL Server 2008R2 上以毫秒为单位返回 DATEDIFF

如何从以毫秒为单位的长度中找到以帧、字节和整数为单位的音符长度

以毫秒为单位偏移当前系统时间到时区 GMT