simpledateformat parsing date with 'Z' literal
我试图解析一个看起来像这样的日期:
1 | 2010-04-05T17:16:00Z |
这是http://www.ietf.org/rfc/rfc3339.txt的有效日期。 'Z'字面意思"暗示UTC
是指定时间的首选参考点。"
如果我尝试使用SimpleDateFormat和此模式解析它:
1 | yyyy-MM-dd'T'HH:mm:ss |
它将被解析为2010年4月5日17:16:00美国东部时间2010年
SimpleDateFormat无法使用以下模式解析字符串:
1 2 | yyyy-MM-dd'T'HH:mm:ssz yyyy-MM-dd'T'HH:mm:ssZ |
我可以显式设置TimeZone在SimpleDateFormat上使用以获得预期的输出,但我不认为这是必要的。 有什么我想念的吗? 有替代日期解析器吗?
Java无法正确解析ISO日期。
与McKenzie的答案类似。
只需在解析之前修复
码
1 2 3 4 5 6 7 | 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)); |
结果
1 2 3 | string: 2013-03-05T18:05:05.000Z defaultTimezone: America/New_York date: 2013-03-05T13:05:05.000-0500 |
您要解析的日期是ISO8601格式。
在java 7中,要读取和应用时区后缀的模式应为
在该模式中,包含'z'日期时间组件表示时区格式需要符合通用时区"标准",其示例是
"Z"表示时区符合RFC 822时区标准,例如,
我想你需要一个DatatypeConverter ......
1 2 3 4 5 | @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()); } |
TL;博士
1 | Instant.parse ("2010-04-05T17:16:00Z" ) |
ISO 8601标准
您的String符合ISO 8601标准(其中提到的RFC 3339是配置文件)。
避免j.u.Date
与Java捆绑在一起的java.util.Date和.Calendar类非常麻烦。避免他们。
而是使用Java 8中的Joda-Time库或新的java.time包。两者都使用ISO 8601作为解析和生成日期时间值的字符串表示的默认值。
java.time
Java 8及更高版本中内置的java.time框架取代了麻烦的旧java.util.Date/.Calendar类。新课程的灵感来自非常成功的Joda-Time框架,旨在作为其继承者,在概念上类似但重新设计。由JSR 310定义。由ThreeTen-Extra项目扩展。请参阅教程。
java.time中的
输入字符串末尾的
1 2 |
转储到控制台。
1 |
instant: 2010-04-05T17:16:00Z
从那里,您可以应用时区(
如果必须使用
乔达时间
Joda-Time 2.5中的示例。
1 2 | DateTimeZone timeZone = DateTimeZone.forID("Europe/Paris" ): DateTime dateTime = new DateTime("2010-04-05T17:16:00Z", timeZone ); |
转换为UTC。
1 | DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC ); |
如有必要,转换为java.util.Date。
1 |
根据Java 7 API的日期和时间模式表的最后一行
X时区ISO 8601时区-08;-0800;-08:00
对于ISO 8601时区,您应该使用:
- X代表(-08或Z),
- XX为(-0800或Z),
- XXX代表(-08:00或Z);
所以要解析你的"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"。
1 2 3 | 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")); |
将正确打印出'Mon Apr 05 13:16:00 EDT 2010'
'X'仅在部分秒不存在时才有效:即SimpleDateFormat模式
"YYYY-MM-dd'T'HH:MM:SSX"
将正确解析
"2008-01-31T00:00:00Z"
但
"YYYY-MM-dd'T'HH:MM:ss.SX"
不会解析
"2008-01-31T00:00:00.000Z"
可悲但真实,带有部分秒数的日期时间似乎不是有效的ISO日期:http://en.wikipedia.org/wiki/ISO_8601
时区应该是"GMT + 00:00"或0000,以便由SimpleDateFormat正确解析 - 您可以用这种结构替换Z.
关于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.
如果您正在处理Android项目,则可能需要签出ThreeTenABP库。
1 | 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.
我提供了另一个由Google
1 2 3 4 5 6 7 8 | 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(); } |
安装指南,
https://developers.google.com/api-client-library/java/google-api-java-client/setup#download
这是API参考,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime
源代码
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime.java
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api/client/util/DateTimeTest.java#L121
restlet项目包含一个可以解析RFC 3339日期的InternetDateFormat类。
Restlet InternetDateFormat
但是,您可能只想在解析之前将"Z"替换为"UTC"。
在Java 8下,使用预定义的DateTimeFormatter.ISO_DATE_TIME
1 2 | DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME; ZonedDateTime result = ZonedDateTime.parse("2010-04-05T17:16:00Z", formatter); |
我想这是最简单的方法
因为java 8只使用