Java SimpleDateFormat 用“Z”字面量解析日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2580925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:28:39  来源:igfitidea点击:

SimpleDateFormat parsing date with 'Z' literal

javadatetimeparsingtimezonesimpledateformat

提问by DanInDC

I am trying to parse a date that looks like this:

我正在尝试解析如下所示的日期:

2010-04-05T17:16:00Z

2010-04-05T17:16:00Z

This is a valid date per http://www.ietf.org/rfc/rfc3339.txt. The 'Z' literal (quote) "imply that UTC is the preferred reference point for the specified time."

这是每个http://www.ietf.org/rfc/rfc3339.txt的有效日期。'Z' 文字(引号)“暗示 UTC 是指定时间的首选参考点。

If I try to parse it using SimpleDateFormat and this pattern:

如果我尝试使用 SimpleDateFormat 和这种模式解析它:

yyyy-MM-dd'T'HH:mm:ss

it will be parsed as a Mon Apr 05 17:16:00 EDT 2010

它将被解析为 Mon Apr 05 17:16:00 EDT 2010


SimpleDateFormatis unable to parse the string with these patterns:


SimpleDateFormat无法解析具有以下模式的字符串:

yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssZ

I can explicitly set the TimeZoneto use on the SimpleDateFormatto get the expected output, but I don't think that should be necessary. Is there something I am missing? Is there an alternative date parser?

我可以显式设置TimeZone以用于SimpleDateFormat获得预期的输出,但我认为这没有必要。有什么我想念的吗?有替代的日期解析器吗?

采纳答案by Paul McKenzie

In the pattern, the inclusion of a 'z' date-time component indicates that timezone format needs to conform to the General time zone"standard", examples of which are Pacific Standard Time; PST; GMT-08:00.

在该模式中,包含“z”日期时间组件表示时区格式需要符合通用时区“标准”,例如Pacific Standard Time; PST; GMT-08:00.

A 'Z' indicates that the timezone conforms to the RFC 822 time zonestandard, e.g. -0800.

'Z' 表示时区符合RFC 822 时区标准,例如-0800

I think you need a DatatypeConverter ...

我认为你需要一个 DatatypeConverter ...

@Test
public void testTimezoneIsGreenwichMeanTime() throws ParseException {
    final Calendar calendar = javax.xml.bind.DatatypeConverter.parseDateTime("2010-04-05T17:16:00Z");
    TestCase.assertEquals("gotten timezone", "GMT+00:00", calendar.getTimeZone().getID());
}

回答by Cornel Creanga

The time zone should be something like "GMT+00:00" or 0000 in order to be properly parsed by the SimpleDateFormat - you can replace Z with this construction.

时区应该类似于“GMT+00:00”或 0000 以便被 SimpleDateFormat 正确解析 - 您可以用这种结构替换 Z。

回答by Marcus Adams

The restlet project includes an InternetDateFormat class that can parse RFC 3339 dates.

restlet 项目包括一个 InternetDateFormat 类,可以解析 RFC 3339 日期。

Restlet InternetDateFormat

Restlet InternetDateFormat

Though, you might just want to replace the trailing 'Z' with "UTC" before you parse it.

但是,您可能只想在解析它之前用“UTC”替换尾随的“Z”。

回答by Alex

Java doesn't parse ISO dates correctly.

Java 不能正确解析 ISO 日期。

Similar to McKenzie's answer.

类似于麦肯齐的回答。

Just fix the Zbefore parsing.

只需修复Z之前的解析。

Code

代码

String string = "2013-03-05T18:05:05.000Z";
String defaultTimezone = TimeZone.getDefault().getID();
Date date = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).parse(string.replaceAll("Z$", "+0000"));

System.out.println("string: " + string);
System.out.println("defaultTimezone: " + defaultTimezone);
System.out.println("date: " + (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).format(date));

Result

结果

string: 2013-03-05T18:05:05.000Z
defaultTimezone: America/New_York
date: 2013-03-05T13:05:05.000-0500

回答by Dave Patterson

The date you are parsing is in ISO 8601format.

您解析的日期采用ISO 8601格式。

In Java 7 the pattern to read and apply the timezone suffix should read yyyy-MM-dd'T'HH:mm:ssX

在 Java 7 中,读取和应用时区后缀的模式应为 yyyy-MM-dd'T'HH:mm:ssX

回答by Basil Bourque

tl;dr

tl;博士

Instant.parse ( "2010-04-05T17:16:00Z" )


ISO 8601 Standard

ISO 8601 标准

Your String complies with the ISO 8601standard (of which the mentioned RFC 3339is a profile).

您的字符串符合ISO 8601标准(其中提到的RFC 3339是一个配置文件)。

Avoid java.util.Date

避免 java.util.Date

The java.util.Date and .Calendar classes bundled with Java are notoriously troublesome. Avoid them.

与 Java 捆绑在一起的 java.util.Date 和 .Calendar 类是出了名的麻烦。避开它们。

Instead use either the Joda-Timelibrary or the new java.time package in Java 8. Both use ISO 8601 as their defaults for parsing and generating string representations of date-time values.

而是使用Joda-Time库或 Java 8 中的新 java.time 包。两者都使用 ISO 8601 作为解析和生成日期时间值的字符串表示的默认值。

java.time

时间

The java.timeframework built into Java 8 and later supplants the troublesome old java.util.Date/.Calendar classes. The new classes are inspired by the highly successful Joda-Timeframework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extraproject. See the Tutorial.

Java 8 及更高版本中内置的java.time框架取代了麻烦的旧 java.util.Date/.Calendar 类。新类的灵感来自非常成功的Joda-Time框架,作为其继承者,概念相似但重新构建。由JSR 310定义。由ThreeTen-Extra项目扩展。请参阅教程

The Instantclass in java.time represents a moment on the timeline in UTCtime zone.

Instantjava.time 中的类表示UTC时区时间线上的一个时刻。

The Zat the end of your input string means Zuluwhich stands for UTC. Such a string can be directly parsed by the Instantclass, with no need to specify a formatter.

Z你输入字符串来结束Zulu它代表UTC。这样的字符串可以由Instant类直接解析,无需指定格式化程序。

String input = "2010-04-05T17:16:00Z";
Instant instant = Instant.parse ( input );

Dump to console.

转储到控制台。

System.out.println ( "instant: " + instant );

instant: 2010-04-05T17:16:00Z

即时:2010-04-05T17:16:00Z

From there you can apply a time zone (ZoneId) to adjust this Instantinto a ZonedDateTime. Search Stack Overflow for discussion and examples.

从那里您可以应用时区 ( ZoneId) 将其调整InstantZonedDateTime. 搜索 Stack Overflow 以获取讨论和示例。

If you must use a java.util.Dateobject, you can convert by calling the new conversion methods added to the old classes such as the static method java.util.Date.from( Instant ).

如果必须使用java.util.Date对象,则可以通过调用添加到旧类中的新转换方法(例如静态方法)进行转换java.util.Date.from( Instant )

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

Joda-Time

乔达时间

Example in Joda-Time 2.5.

Joda-Time 2.5 中的示例。

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ):
DateTime dateTime = new DateTime( "2010-04-05T17:16:00Z", timeZone );

Convert to UTC.

转换为 UTC。

DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );

Convert to a java.util.Date if necessary.

如有必要,转换为 java.util.Date。

java.util.Date date = dateTime.toDate();

回答by Sandy McPherson

The 'X' only works if partial seconds are not present: i.e. SimpleDateFormat pattern of

'X' 仅在不存在部分秒的情况下才有效:即 SimpleDateFormat 模式

"yyyy-MM-dd'T'HH:mm:ssX"

“yyyy-MM-dd'T'HH:mm:ssX”

Will correctly parse

会正确解析

"2008-01-31T00:00:00Z"

“2008-01-31T00:00:00Z”

but

"yyyy-MM-dd'T'HH:mm:ss.SX"

“yyyy-MM-dd'T'HH:mm:ss.SX”

Will NOT parse

不会解析

"2008-01-31T00:00:00.000Z"

“2008-01-31T00:00:00.000Z”

Sad but true, a date-time with partial seconds does not appear to be a valid ISO date: http://en.wikipedia.org/wiki/ISO_8601

悲伤但真实,带有部分秒的日期时间似乎不是有效的 ISO 日期:http: //en.wikipedia.org/wiki/ISO_8601

回答by Johnny

I provide another answer that I found by api-client-libraryby Google

我提供了api-client-library由 Google找到的另一个答案

try {
    DateTime dateTime = DateTime.parseRfc3339(date);
    dateTime = new DateTime(new Date(dateTime.getValue()), TimeZone.getDefault());
    long timestamp = dateTime.getValue();  // get date in timestamp
    int timeZone = dateTime.getTimeZoneShift();  // get timezone offset
} catch (NumberFormatException e) {
    e.printStackTrace();
}

Installation guide,
https://developers.google.com/api-client-library/java/google-api-java-client/setup#download

安装指南,
https://developers.google.com/api-client-library/java/google-api-java-client/setup#download

Here is API reference,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime

这是 API 参考,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime

Source code of DateTimeClass,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime.java

DateTime类的源代码,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime .java

DateTimeunit tests,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api/client/util/DateTimeTest.java#L121

DateTime单元测试,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api/client/util/DateTimeTest.java #L121

回答by JJD

With regards to JSR-310 another project of interest might be threetenbp.

关于 JSR-310,另一个感兴趣的项目可能是Threetenbp

JSR-310 provides a new date and time library for Java SE 8. This project is the backport to Java SE 6 and 7.

JSR-310 为 Java SE 8 提供了一个新的日期和时间库。这个项目是 Java SE 6 和 7 的反向移植。

In case you are working on an Androidproject you might want to checkout the ThreeTenABP library.

如果您正在处理Android项目,您可能需要查看ThreeTenABP 库

compile "com.jakewharton.threetenabp:threetenabp:${version}"

JSR-310 was included in Java 8 as the java.time.* package. It is a full replacement for the ailing Date and Calendar APIs in both Java and Android. JSR-310 was backported to Java 6 by its creator, Stephen Colebourne, from which this library is adapted.

JSR-310 作为 java.time.* 包包含在 Java 8 中。它完全替代了 Java 和 Android 中出现问题的 Date 和 Calendar API。JSR-310 由其创建者 Stephen Colebourne 向后移植到 Java 6,该库改编自该库。

回答by Legna

According to last row on the Date and Time Patternstable of the Java 7 API

根据Java 7 API日期和时间模式表的最后一行

X Time zone ISO 8601 time zone -08; -0800; -08:00

X 时区 ISO 8601 时区 -08;-0800; -08:00

For ISO 8601 time zone you should use:

对于 ISO 8601 时区,您应该使用:

  • X for (-08 or Z),
  • XX for (-0800 or Z),
  • XXX for (-08:00 or Z);
  • X 代表(-08 或 Z),
  • XX 代表(-0800 或 Z),
  • XXX 为(-08:00 或 Z);

so to parse your "2010-04-05T17:16:00Z" you can use either "yyyy-MM-dd'T'HH:mm:ssX" or "yyyy-MM-dd'T'HH:mm:ssXX" or "yyyy-MM-dd'T'HH:mm:ssXXX".

所以要解析你的“2010-04-05T17:16:00Z”,你可以使用 “yyyy-MM-dd'T'HH:mm:ssX”或“yyyy-MM-dd'T'HH:mm:ssXX”或 "yyyy-MM-dd'T'HH:mm:ssXXX"

    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2010-04-05T17:16:00Z"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX").parse("2010-04-05T17:16:00Z"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse("2010-04-05T17:16:00Z"));

will correctly print out 'Mon Apr 05 13:16:00 EDT 2010'

将正确打印出“Mon Apr 05 13:16:00 EDT 2010”