simpledateformat parsing date with 'Z' lit

2019-01-01 07:32发布

This question already has an answer here:

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

2010-04-05T17:16:00Z

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

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

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

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

SimpleDateFormat is unable to parse the string with these patterns:

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

I can explicitly set the TimeZone to 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?

12条回答
柔情千种
2楼-- · 2019-01-01 07:42

The date you are parsing is in ISO8601 format.

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

查看更多
骚的不知所云
3楼-- · 2019-01-01 07:46

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.

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

I think you need a 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());
}
查看更多
墨雨无痕
4楼-- · 2019-01-01 07:48

Under Java 8 use the predefined DateTimeFormatter.ISO_DATE_TIME

 DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
 ZonedDateTime result = ZonedDateTime.parse("2010-04-05T17:16:00Z", formatter);

I guess its the easiest way

查看更多
一个人的天荒地老
5楼-- · 2019-01-01 07:49

Java doesn't parse ISO dates correctly.

Similar to McKenzie's answer.

Just fix the Z before parsing.

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
查看更多
公子世无双
6楼-- · 2019-01-01 07:51

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

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

Will correctly parse

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

but

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

Will NOT parse

"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

查看更多
高级女魔头
7楼-- · 2019-01-01 07:57

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.

查看更多
登录 后发表回答