如何以Java或GMT格式获取当前日期和时间?
当我创建一个新的Date
对象时,它被初始化为当前时间,但在本地时区。 我如何在格林威治标准时间获得当前的日期和时间?
java.util.Date
没有特定的时区,尽管它的值通常与UTC有关。 是什么让你认为这是当地时间?
准确地说: java.util.Date
的值是自Unix时代开始的毫秒数,它发生在UTC时间1970年1月1日午夜。 同样的时代也可以在其他时区描述,但传统的描述是以UTC为单位的。 由于它是固定时期以来的毫秒数,因此无论本地时区如何,在任何特定时刻, java.util.Date
的值都是相同的。
我怀疑问题在于,您是通过使用本地时区的日历实例来显示它,或者可能使用也使用本地时区的Date.toString()
或SimpleDateFormat
实例,该实例默认情况下也使用本地时区时区。
如果这不是问题,请发布一些示例代码。
不过,我会建议你使用Joda-Time,它提供了一个更清晰的API。
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
//Local time zone
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
//Time in GMT
return dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
TL;博士
Instant.now() // Capture the current moment in UTC.
生成一个字符串来表示该值:
Instant.now().toString()
2016-09-13T23:30:52.123Z
细节
正如Jon Skeet的正确答案所述,java.util.Date对象没有时区 †。 但是它的toString
实现在生成该日期时间值的字符串表示时应用JVM的默认时区。 混淆天真的程序员,日期似乎有一个时区,但没有。
与Java捆绑在一起的java.util.Date
, juCalendar
和java.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带来全新的Clock
捕捉功能,捕捉当前时刻,达到此类的全纳秒能力,具体取决于主计算机时钟硬件的能力。
它是toString
方法使用一个特定的ISO 8601格式生成其值的字符串表示。 该格式根据需要输出零,三,六或九位数字(毫秒,微秒或纳秒)以表示秒的分数。
如果您想要更灵活的格式,在各种时区或其他附加功能中进行调整,请应用时区( ZoneId
对象)以获取ZonedDateTime
。 时区可以是UTC或任何其他时区。 的子类ZoneId
, ZoneOffset
适用于UTC的常数。
ZonedDateTime now = ZonedDateTime.now( ZoneOffset.UTC );
转储到控制台...
System.out.println( "now: " + now );
当运行...
now: 2014-01-21T23:42:03.522Z
java.time类由JSR 310定义。它们受Joda-Time的启发,但完全重新架构。
乔达时间
更新: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的当前默认时区(可随时更改!)。 这种依赖似乎是日期时间工作中混淆和错误的常见原因。
now()
打电话时now()
通过所需的/预期的时区进行分配。 使用DateTimeZone
类。
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 toString
方法使用的时区; 该方法使用JVM的当前默认时区。 所有更多的理由避免这个令人困惑的类,坚持Joda-Time和java.time。
上一篇: How can I get the current date and time in UTC or GMT in Java?