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
SimpleDateFormat parsing date with 'Z' literal
提问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
SimpleDateFormat
is 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 SimpleDateFormat
to 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 日期。
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 Z
before 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
回答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 Instant
class in java.time represents a moment on the timeline in UTCtime zone.
Instant
java.time 中的类表示UTC时区时间线上的一个时刻。
The Z
at the end of your input string means Zulu
which stands for UTC
. Such a string can be directly parsed by the Instant
class, 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 Instant
into a ZonedDateTime
. Search Stack Overflow for discussion and examples.
从那里您可以应用时区 ( ZoneId
) 将其调整Instant
为ZonedDateTime
. 搜索 Stack Overflow 以获取讨论和示例。
If you must use a java.util.Date
object, 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-library
by 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
Source code of DateTime
Class,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime.java
DateTime
unit 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
回答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”