如何以毫秒为单位返回 LocalDate.now()? [英] How can I return LocalDate.now() in milliseconds?

查看:70
本文介绍了如何以毫秒为单位返回 LocalDate.now()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在创建日期:

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

然后我想以毫秒为单位返回这个日期:

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

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

解决方案

调用 toInstant().toEpochMilli(),如 @JB Nizet 的评论,是正确的答案,但是关于使用本地日期有一个小而棘手的细节,你必须注意.

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

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

现在是棘手的细节:当您调用 now() 方法时(对于 LocalDateTimeLocalDate),它使用 JVM 的默认值timezone 获取当前日期的值,该值可能会根据 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-23System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());

输出是:

<块引用>

1503446400000

相当于 UTC 时间 2017 年 8 月 23th 午夜.

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

<块引用>

1503360000000

相当于 2017 年 8 月 22th UTC 午夜.

使用 now() 使您的代码依赖于 JVM 的默认时区.并且此配置即使在运行时也可以更改,恕不另行通知,从而使您的代码在发生此类更改时返回不同的结果.p>

而且您不需要这种极端情况(例如有人将 JVM 错误配置为非常远"的时区).例如,在 America/Sao_Paulo 时区,如果我在 11 PM 运行代码,LocalDate 将返回 August 22th,但当前的 UTC 日期已经是 8 月 23th.这是因为圣保罗的晚上 11 点与 UTC第二天 的凌晨 2 点相同:

//2017 年 8 月 22 日,晚上 11 点,圣保罗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[美国/圣保罗]System.out.println(z.toInstant());//2017-08-23T02:00:00Z(UTC 时间已经是 8 月 23 日)

因此,使用 LocalDate.now() 保证我将始终拥有 UTC 中的当前日期..p><小时>

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

//UTC 的当前日期,无论 JVM 默认时区是什么ZonedDateTime zdtNow = ZonedDateTime.now(ZoneOffset.UTC);//将时间设置为午夜并获取 epochMilliSystem.out.println(zdtNow.with(LocalTime.MIDNIGHT).toInstant().toEpochMilli());

输出是:

<块引用>

1503360000000

相当于 2017 年 8 月 22th UTC 午夜.

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

//UTC 的当前日期,无论 JVM 默认时区是什么LocalDate dtNowUtc = LocalDate.now(ZoneOffset.UTC);//将时间设置为午夜并获取 epochMilliSystem.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());

I create date now:

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

Then I want return this date in milliseconds:

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

How can I return LocalDate.now() in milliseconds?

解决方案

Calling toInstant().toEpochMilli(), as suggested by @JB Nizet's comment, is the right answer, but there's a little and tricky detail about using local dates that you must be aware of.

But before that, some other minor details:

  • Instead of ZoneId.of("GMT") you can use the built-in constant ZoneOffset.UTC. They're equivalent, but there's no need to create extra redundant objects if the API already provides one that does exactly the same thing.
  • Instead of calling LocalDateTime.now() and then .toLocalDate(), you can call LocalDate.now() directly - they're equivalent.

Now the tricky details: when you call the now() method (for either LocalDateTime or LocalDate), it uses the JVM's default timezone to get the values for the current date, and this value might be different depending on the timezone configured in the JVM.

In the JVM I'm using, the default timezone is America/Sao_Paulo, and the local time here is 09:37 AM. So LocalDate.now() returns 2017-08-22 (August 22th 2017).

But if I change the default timezone to Pacific/Kiritimati, it returns 2017-08-23. That's because in Kiritimati, right now is already August 23th 2017 (and the local time there, at the moment I write this, is 02:37 AM).

So, if I run this code when the default timezone is Pacific/Kiritimati:

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

The output is:

1503446400000

Which is the equivalent of August 23th 2017 at midnight in UTC.

If I run the same code when the default timezone is America/Sao_Paulo, the result will be:

1503360000000

Which is the equivalent of August 22th 2017 at midnight in UTC.

Using now() makes your code depends on the JVM's default timezone. And this configuration can be changed without notice, even at runtime, making your code return different results when such change occurs.

And you don't need such an extreme case (like someone misconfiguring the JVM to a "very-far" timezone). In my case, for example, in America/Sao_Paulo timezone, if I run the code at 11 PM, LocalDate will return August 22th, but the current date in UTC will already be August 23th. That's because 11 PM in São Paulo is the same as 2 AM of the next day in UTC:

// 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)

So using a LocalDate.now() is not a guarantee that I'll always have the current date in UTC.


If you want the current date in UTC (regardless of the JVM default timezone) and set the time to midnight, it's better to use a 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());

The output is:

1503360000000

Which is the equivalent of August 22th 2017 at midnight in UTC.

Another alternative is to pass the timezone to LocalDate.now, so it can get the correct values for the current date on the specified zone:

// 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()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆