在 Java 中解析 ISO 8601 日期格式,如 2015-06-27T13:16:37.363Z

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31090946/
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-11-02 18:06:00  来源:igfitidea点击:

Parsing ISO 8601 date format like 2015-06-27T13:16:37.363Z in Java

javadatesimpledateformatiso8601

提问by Guy

I am trying to parse a Stringusing SimpleDateFormat.

我正在尝试解析一个Stringusing SimpleDateFormat

This is my current code:

这是我当前的代码:

public String getCreatedDateTime() {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-ddEHH:mm:ss.zzzz");
    try {
        Date date = simpleDateFormat.parse("2015-06-27T13:16:37.363Z");
        return date.toString();
    } catch (ParseException e) {
        return "Error parsing date";
    }
}

As you can see, I just put a constant in the parse() method for testing purposes.

如您所见,我只是在 parse() 方法中放置了一个常量以进行测试。

So, this is what I am trying to parse:

所以,这就是我想要解析的:

2015-06-27T13:16:37.363Z

2015-06-27T13:16:37.363Z

This is the SimpleDateFormatpattern that I am using:

这是SimpleDateFormat我正在使用的模式:

yyyy-MM-ddEHH:mm:ss.zzzz

yyyy-MM-ddEHH:mm:ss.zzzz

I keep getting the ParseException.

我不断收到 ParseException。

I know that it is proably because of the .zzzz at the end but I have no idea what .363Z might stand for so I just used some random letters. Bad idea.

我知道这可能是因为最后的 .zzzz 但我不知道 .363Z 可能代表什么,所以我只是使用了一些随机字母。馊主意。

I'll appreciate your help a lot. Thank you!

我会非常感谢你的帮助。谢谢!

回答by eugenioy

Try with this pattern (note the X at the end and the 'T' in the middle):

尝试使用这种模式(注意末尾的 X 和中间的“T”):

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

From Java's SimpleDateFormat's documentation:

来自 Java 的SimpleDateFormat 的文档

ISO 8601 Time zone:

...

For parsing, "Z" is parsed as the UTC time zone designator.

ISO 8601 时区:

...

对于解析,“Z”被解析为 UTC 时区指示符。

And, from the part where it describes the different characters:

并且,从它描述不同字符的部分开始:

X - Time zone - ISO 8601 time zone

X - 时区 - ISO 8601 时区

EDIT

编辑

If using Android, then "X" is not supported.

如果使用 Android,则不支持“X”。

You can use this pattern (note Z is a literal now):

你可以使用这个模式(注意 Z 现在是一个文字):

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

But then you'll get the date on your current timezone and would need to convert it to UTC if needed.

但是,您将获得当前时区的日期,并且需要在需要时将其转换为 UTC。

回答by Basil Bourque

tl;dr

tl;博士

Skip the formatting pattern. Standard ISO 8601format is used by default.

跳过格式模式。默认使用标准ISO 8601格式。

Instant.parse( "2015-06-27T13:16:37.363Z" )


ISO 8601

ISO 8601

Your string format is formally defined by the ISO 8601standard.

您的字符串格式由ISO 8601标准正式定义。

Basically your Question is a duplicate of this one, Converting ISO 8601-compliant String to java.util.Date.

基本上你的问题是这个问题的重复,将符合 ISO 8601 的 String 转换为 java.util.Date

Alternatives

备择方案

The Answerby eugenioyis correct.

答案eugenioy是正确的。

But you should know that the old java.util.Date/.Calendar/java.text.SimpleDateFormat classes bundled with Java are notoriously troublesome and should be avoided.

但是您应该知道与 Java 捆绑在一起的旧 java.util.Date/.Calendar/java.text.SimpleDateFormat 类是出了名的麻烦,应该避免。

Outmoded Classes

过时的课程

Those old classes are now outmoded, first by the third-party Joda-Timelibrary, and now by the new java.time package(Tutorial) built into Java 8 and later (inspired by Joda-Time, defined by JSR 310, extended by the ThreeTen-Extraproject).

那些旧的类现在已经过时了,首先是由第三方Joda-Time库,现在是由内置于 Java 8 及更高版本中的新java.time 包教程)(受JSR 310定义的 Joda-Time 启发,扩展为在ThreeTen-EXTRA项目)。

Both java.time and Joda-Time use the ISO 8601 standard as their defaults when parsing/generating string representations of date-time values. So the code is simple, no need for custom formatter objects. No need for all that format twiddling that caused your Exception.

在解析/生成日期时间值的字符串表示时,java.time 和 Joda-Time 都使用 ISO 8601 标准作为它们的默认值。所以代码很简单,不需要自定义格式化程序对象。不需要所有导致异常的格式。

Time Zone

时区

Both java.time and Joda-Time have a zoned date-time class that understands its assigned time zone (unlike java.util.Date). If you do not assign one, the JVM's current default time zone is assigned.

java.time 和 Joda-Time 都有一个分区日期时间类,它了解其分配的时区(与 java.util.Date 不同)。如果不分配,则分配 JVM 的当前默认时区。

Beware that the JVM's current default time zone can change at any time. It can change at deployment, defaulting to whatever the host OS setting is. And it can change at any moment during runtime when any code in any thread of any app within the JVM calls TimeZone.setDefault. So better to explicitly assign a desired/expected time zone.

要注意的是JVM的当前默认时区可以更改在任何时间。它可以在部署时更改,默认为任何主机操作系统设置。当 JVM 中任何应用程序的任何线程中的任何代码调用时,它可以在运行时随时更改TimeZone.setDefault。因此最好明确分配所需/预期的时区。

java.time

时间

The Zon the end of your string is short for Zulu and means UTC. The Instantclass can directly parse that format, to represent a moment on the timeline in UTC with a resolution in nanoseconds.

Z你的字符串的结尾是短期的祖鲁语和手段UTC。本Instant类,可直接解析该格式,以表示UTC时间线,在纳秒的分辨率上一会儿。

String input = "2015-06-27T13:16:37.363Z";
Instant instant = Instant.parse( input );

Change the time zone from UTC to some desired/expected time zone.

将时区从 UTC 更改为某个所需/预期的时区。

ZoneID zone = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdtMontréal = instant.atZone( zone ) ;

If you really need a java.util.Date for interoperability, convert.

如果您确实需要 java.util.Date 来实现互操作性,请转换。

java.util.Date utilDate = Date.from( zdtMontréal.toInstant() ) ;

Joda-Time

乔达时间

The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes:

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

Note that from Java SE 8 onwards, users are asked to migrate to java.time(JSR-310) - a core part of the JDK which replaces this project.

请注意,从 Java SE 8 开始,要求用户迁移到java.time(JSR-310) - 替代该项目的 JDK 的核心部分。

Example code using Joda-Time 2.8.1.

使用 Joda-Time 2.8.1 的示例代码。

String input = "2015-06-27T13:16:37.363Z" ;
DateTimeZone zone = DateTimeZone.UTC ;  //  Or: DateTimeZone.forID( "America/Montreal" ) ;
DateTime dateTime = new DateTime( input, zone ) ;

If you really need a java.util.Date for interoperability, convert.

如果您确实需要 java.util.Date 来实现互操作性,请转换。

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


About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

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

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多