在 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
Parsing ISO 8601 date format like 2015-06-27T13:16:37.363Z in Java
提问by Guy
I am trying to parse a String
using SimpleDateFormat
.
我正在尝试解析一个String
using 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 SimpleDateFormat
pattern 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.
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 Z
on the end of your string is short for Zulu and means UTC. The Instant
class 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 类?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Most of the java.timefunctionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.timeclasses.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 大多数java.time功能在ThreeTen-Backport 中被反向移植到 Java 6 & 7 。
- 安卓
- 更高版本的 Android 捆绑实现java.time类。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
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 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。