如何在Java 8中获取UTC + 0日期?


108

我在Java中的Date类有问题。日期类返回本地机器日期,但我需要UTC-0。

我已经搜寻了一下,找到了JavaScript的绝佳解决方案,但Java却没什么用。

如何在Java 8中获取UTC + 0日期?


12
java.util.Date绝不是本地计算机日期。自1970年1月1日起,相对于UTC + 00:00,始终将其定义为经过的毫秒数。也许其方法的行为toString()使您感到困惑,而这确实在本地时区使用了表示形式。
Meno Hochschild 2014年

:一个可能的答案可以在问题中找到stackoverflow.com/questions/45350095/...
普里亚耆那教

Answers:


146

使用Java 8,您可以编写:

OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

要回答您的评论,您可以将其转换为日期(除非您依赖于旧代码,我看不到任何原因)或自时代以来转换为毫。

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toEpochSecond() * 1000;

1
谢谢。是否可以将ZonedDateTime转换为Date或long(ms)?
2014年

7
尽管此Answer的代码在技术上有效,但使用OffsetDateTime而不是ZonedDateTime假设我们仅使用距UTC的偏移量而不是整个时区工作,这会更合适吗?
罗勒·布尔克

179

tl; dr

Instant.now()

java.time

与Java最早版本捆绑在一起的麻烦的旧日期时间类已由内置在Java 8及更高版本中的java.time类所取代。请参阅Oracle教程。许多功能已被后移植到Java 6和7在ThreeTen-反向移植和在进一步适于到Android ThreeTenABP

Instant

An Instant代表UTC时间线上的一个时刻,分辨率最高为ns

Instant instant = Instant.now();

toString方法使用标准ISO 8601格式之一生成带有文本的String对象,该文本表示日期时间值。

String output = instant.toString();  

2016-06-27T19:15:25.864Z

Instant班是java.time一个基本构建块类。在处理日期时间时,这应该是您的首选课程,因为最佳实践通常是在UTC中跟踪,存储和交换日期时间值。

OffsetDateTime

但是Instant有局限性,例如没有格式选项可用于生成备用格式的字符串。要获得更大的灵活性,请从转换InstantOffsetDateTime。指定从UTC偏移量。在java.time中,这意味着一个ZoneOffset对象。在这里,我们要坚持使用UTC(+00),以便可以使用便捷的常量ZoneOffset.UTC

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );

2016-06-27T19:15:25.864Z

或跳过Instant课程。

OffsetDateTime.now( ZoneOffset.UTC )

现在有了一个OffsetDateTime对象,您就可以DateTimeFormatter用来创建具有替代格式文本的String对象。在Search Stack Overflow中搜索有关使用的许多示例DateTimeFormatter

ZonedDateTime

当您要显示某个特定时区的挂钟时间时,请应用ZoneId来获取ZonedDateTime

在此示例中,我们应用蒙特利尔时区。在夏季,在“ 夏令时(DST)”无意义的情况下,该区域的偏移量为-04:00。因此请注意如何在时间的天是在输出前面四个小时,15而不是19小时。Instant并且ZonedDateTime都表示非常相同的同时时刻,只是通过两个不同的镜头看。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

2016-06-27T15:15:25.864-04:00 [美国/蒙特利尔]

转换中

虽然您应该避免使用旧的日期时间类,但如果必须,则可以使用添加到旧类中的新方法进行转换。在这里,我们使用java.util.Date.from( Instant )java.util.Date::toInstant

java.util.Date utilDate = java.util.Date.from( instant );

并朝另一个方向发展。

Instant instant= utilDate.toInstant();

同样,寻找添加到的GregorianCalendar子类中的新方法Calendar以与进行转换java.time.ZonedDateTime

现代java.time与旧版中日期时间类的类型表。

关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。Hibernate 5和JPA 2.2支持java.timejava.sql.*

在哪里获取java.time类?


3
赞赏说DST是
胡说八道

因此,如果DST不存在,ZonedDateTime就不需要使用DST了,因为所有DST 都ZoneId可以映射到ZoneOffset我们可以使用的DST上OffsetDateTime
wilmol

1
@wilmol号。夏令时(DST)只是政客选择重新定义时区边界和这些时区中的偏移量的众多原因之一。最近,出于外交原因,北朝鲜将时钟更改为半小时与南韩同步。在战争中,侵略者/占领者可能会更改补偿以匹配本国的补偿。目前,正是各国政府都选择停止DST的变化,而且是永久呆在一个新玩意 DST,而不是恢复到它们以前的标准时间。始终计划每个区域更改的偏移量,否则您的应用最终将崩溃。
罗勒·布尔克

1
很棒的答案!我非常感谢您投入的时间。:)
drognisep

ZoneId.of(“美国/蒙特利尔”); 为什么有人会在jdk中发明这种东西?丑陋,令人作呕,直到运行时才告诉您是否有什么问题,谁能记住所有这些硬代码?为什么不将其隐含在ENUM类中?
workplaylifecycle

4

在java8中,我将使用UTC中Instant已经存在且易于使用的类。

import java.time.Instant;

Instant ins = Instant.now();
long ts = ins.toEpochMilli();

Instant ins2 = Instant.ofEpochMilli(ts)

另外,您可以使用以下方法:

import java.time.*;

Instant ins = Instant.now(); 

OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));

回到 Instant

Instant ins4 = Instant.from(odt);

3
不,一个Instant不是在本地时间。根据Instant定义,此格式为UTC。因此,无需尝试在本答案中看到的企图进入UTC;在Instant已经在UTC。有关更多信息和更简单的代码,请参见我的答案
罗勒·布尔克

感谢您的评论。
Abel Terefe


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.