如何以 UTC 或 GMT 格式获取 Java 格式的当前日期和时间?tl;博士详java.time (Java 8)关于 java.time 城大时间时区国际标准化组织 ISO 8601

2022-08-31 04:18:23

当我创建一个新对象时,它被初始化为当前时间,但采用本地时区。如何获取 GMT 的当前日期和时间?Date


答案 1

tl;博士

Instant.now()   // Capture the current moment in UTC. 

生成一个字符串来表示该值:

Instant.now().toString()  

2016-09-19T10:49:52.123Z

正如Jon Skeet的正确答案所说,java.util.Date对象没有时区。但是它的 toString 实现在生成该日期时间值的 String 表示形式时应用 JVM 的默认时区。对于天真的程序员来说,令人困惑的是,日期似乎有时区,但没有时区。

与 Java 捆绑在一起的 、 和类是出了名的麻烦。避免它们。相反,请使用以下任一称职的日期时间库:java.util.Datej.u.Calendarjava.text.SimpleDateFormat

java.time (Java 8)

Java 8 带来了一个出色的新 java.time.* 包来取代旧的 java.util.Date/Calendar 类。

以UTC / GMT获取当前时间是一个简单的单行...

Instant instant = Instant.now();

Instant 类是 java.time 中的基本构建块,表示 UTC 时间轴上的一个时刻,分辨率为纳秒

在 Java 8 中,捕获当前时刻的分辨率最高可达毫秒。Java 9 带来了时钟的全新实现它捕获当前时刻的能力最高可达此类的全部纳秒级,具体取决于主机时钟硬件的能力。

它的方法使用一种特定的ISO 8601格式生成其值的字符串表示形式。该格式根据需要输出零位、三位、六位或九位数字(毫秒微秒纳秒)来表示秒的分数。toString

如果需要更灵活的格式或其他附加功能,请为 UTC 本身应用与 UTC 的偏移量为零(ZoneOffset.UTC 常量)以获取 OffsetDateTime

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

转储到控制台...

System.out.println( "now.toString(): " + now );

运行时...

now.toString(): 2014-01-21T23:42:03.522Z

Table of date-time types in Java, both modern and legacy.


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

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

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

从哪里获取 java.time 类?

Table of which java.time library to use with which version of Java or Android

ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter


城大时间

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

使用Joda-Time第三方开源免费库,您只需一行代码即可获得当前日期时间。

Joda-Time启发了Java 8中新的java.time.*类,但具有不同的体系结构。您可以在旧版本的Java中使用Joda-Time。Joda-Time继续在Java 8中工作,并继续积极维护(截至2014年)。但是,Joda-Time团队确实建议迁移到java.time。

System.out.println( "UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime( org.joda.time.DateTimeZone.UTC ) );

更详细的示例代码 (Joda-Time 2.3)...

org.joda.time.DateTime now = new org.joda.time.DateTime(); // Default time zone.
org.joda.time.DateTime zulu = now.toDateTime( org.joda.time.DateTimeZone.UTC );

转储到控制台...

System.out.println( "Local time in ISO 8601 format: " + now );
System.out.println( "Same moment in UTC (Zulu): " + zulu );

运行时...

Local time in ISO 8601 format: 2014-01-21T15:34:29.933-08:00
Same moment in UTC (Zulu): 2014-01-21T23:34:29.933Z

有关执行时区工作的更多示例代码,请参阅我对类似问题的回答。

时区

我建议您始终指定时区,而不是隐式依赖 JVM 的当前默认时区(可以随时更改!这种依赖似乎是日期时间工作中混淆和错误的常见原因。

呼叫时,传递要分配的所需/预期时区。使用 DateTimeZone 类。now()

DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );

该类在 UTC 时区中保持一个常量

DateTime now = DateTime.now( DateTimeZone.UTC );

如果您确实想使用 JVM 的当前默认时区,请进行显式调用,以便您的代码可以自我记录。

DateTimeZone zoneDefault = DateTimeZone.getDefault();

国际标准化组织 ISO 8601

阅读有关 ISO 8601 格式的信息。java.time和Joda-Time都使用该标准的合理格式作为解析和生成字符串的默认值。


实际上,java.util.Date确实有一个时区,深埋在源代码层之下。出于大多数实际目的,该时区将被忽略。因此,作为简写,我们说java.util.Date没有时区。此外,该被掩埋的时区不是Date方法使用的时区;该方法使用 JVM 的当前默认时区。更有理由避免这个令人困惑的类,并坚持使用Joda-Time和java.time。toString


答案 2

java.util.Date没有特定的时区,尽管它的值最常被认为是与 UTC 相关的。是什么让你认为它是在当地时间?

确切地说:a 内的值是自 Unix 时代以来的毫秒数,该时代发生在 1970 年 1 月 1 日午夜 UTC。同一纪元也可以在其他时区中描述,但传统的描述是UTC。由于这是自固定纪元以来的几毫秒,因此无论本地时区如何,世界各地的值在世界上都是相同的。java.util.Datejava.util.Date

我怀疑问题是你通过使用本地时区的日历实例显示它,或者可能使用也使用本地时区,或者使用实例,默认情况下,它也使用本地时区。Date.toString()SimpleDateFormat

如果这不是问题所在,请发布一些示例代码。

但是,我建议您无论如何都使用Joda-Time,它提供了更清晰的API。