By DanInDC


2010-04-05 20:17:08 8 Comments

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 comments

@Legna 2016-05-11 21:41:01

According to last row on the Date and Time Patterns table of the Java 7 API

X Time zone ISO 8601 time zone -08; -0800; -08:00

For ISO 8601 time zone you should use:

  • X for (-08 or Z),
  • XX for (-0800 or Z),
  • XXX for (-08:00 or 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" .

    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'

@davidgyoung 2017-12-21 16:38:40

This should be the accepted answer, because it shows how to parse the date string using SimpleDateFormat like the question asked.

@DuĊĦan Zahoranský 2017-11-06 01:12:47

Since java 8 just use ZonedDateTime.parse("2010-04-05T17:16:00Z")

@Basil Bourque 2014-06-25 06:32:56

tl;dr

Instant.parse ( "2010-04-05T17:16:00Z" )

ISO 8601 Standard

Your String complies with the ISO 8601 standard (of which the mentioned RFC 3339 is a profile).

Avoid j.u.Date

The java.util.Date and .Calendar classes bundled with Java are notoriously troublesome. Avoid them.

Instead use either the Joda-Time library 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.

java.time

The java.time framework 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-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.

The Instant class in java.time represents a moment on the timeline in UTC time zone.

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.

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

From there you can apply a time zone (ZoneId) to adjust this Instant into a ZonedDateTime. Search Stack Overflow for discussion and examples.

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 date = java.util.Date.from( instant );

Joda-Time

Example in Joda-Time 2.5.

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ):
DateTime dateTime = new DateTime( "2010-04-05T17:16:00Z", timeZone );

Convert to UTC.

DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );

Convert to a java.util.Date if necessary.

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

@JJD 2016-03-24 14:05:25

Please mind this article by Stephen Colebourne: Why JSR-310 isn't Joda-Time

@JavaBohne 2017-05-03 08:25:19

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

@JJD 2016-03-24 14:29:46

With regards to JSR-310 another project of interest might be 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.

In case you are working on an Android project you might want to checkout the ThreeTenABP library.

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.

@Johnny 2016-03-17 08:15:47

I provide another answer that I found by api-client-library by 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

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

@Alex 2013-03-05 18:40:23

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

@Raphael Jolivet 2013-11-19 09:56:07

What a shame ! Thanks for the tip

@Dave Patterson 2014-06-24 21:39:17

Java 7 added pattern letter X to parse ISO dates.

@Alex 2014-09-04 16:02:30

@Dave, thanks for the update!

@Basil Bourque 2015-12-04 07:08:05

"Java doesn't parse ISO dates correctly." -- Well, old Java does not. However, new Java does (Java 8 and later). See the new java.time framework.

@Chris 2017-01-23 03:41:56

Unfortunately a lot of us have to support older Java, such as Android phones pre-Android 7. (The Z pattern letter throws an exception on Android 6.)

@Sandy McPherson 2015-03-23 12:23:50

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

@Daniel F 2015-07-20 14:02:09

This is terribly annoying.

@MGM 2015-12-03 23:23:37

Quote from referenced wiki page: "Decimal fractions may be added to any of the three time elements. [...] There is no limit on the number of decimal places for the decimal fraction. However, the number of decimal places needs to be agreed to by the communicating parties." The "Z" is an independent notion for time zones. So partial seconds ARE valid ISO dates. It would be nice to parse. (Maybe it is not a "Simple Date Format"? ;) )

@Dave Patterson 2014-06-24 18:46:52

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

@Ejaz Ahmed 2016-07-27 12:59:13

This should have been the correct answer instead of accepted answer.

@mateuscb 2017-05-05 14:07:40

Also, if you want to parse the minutes in the timezone, simply add a second or third X: yyyy-MM-dd'T'HH:mm:ssXX or yyyy-MM-dd'T'HH:mm:ssXXX. More details see SimpleDateFormat - ISO 8601 Time zone.

@Paul McKenzie 2010-04-05 20:47:36

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());
}

@DanInDC 2010-04-05 21:09:43

yes, I understand that. The z/Z permutations were just me seeing if anything would stick. It still remains that my date is valid and there should be a valid pattern to parse it.

@Paul McKenzie 2010-04-05 21:21:57

I was struggling to remember the class DatatypeConverter which a colleague showed me only recently.

@Paul McKenzie 2010-04-05 21:26:43

Also see previous stackoverflow.com/questions/2201925/… answer

@Jörn Horstmann 2010-04-05 21:30:39

Thanks, I haven't seen this class before. It also seems there is finally a BASE64 en/decoder in the standard jdk classes :)

@Legna 2016-05-11 21:31:59

upgrade to java 7 (at least) and you will able to parsed

@Kimball Robinson 2017-04-22 17:06:23

The third answer with the 'X' in the format string is the most correct/up to date.

@Marcus Adams 2010-04-05 20:57:27

The restlet project includes an InternetDateFormat class that can parse RFC 3339 dates.

Restlet InternetDateFormat

Though, you might just want to replace the trailing 'Z' with "UTC" before you parse it.

@emmby 2010-05-18 18:54:11

Restlet InternetDateFormat worked well for me

@Cornel Creanga 2010-04-05 20:36:09

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.

Related Questions

Sponsored Content

29 Answered Questions

[SOLVED] How Do You Parse and Process HTML/XML in PHP?

35 Answered Questions

[SOLVED] Compare two dates with JavaScript

25 Answered Questions

[SOLVED] How do I parse a string to a float or int in Python?

34 Answered Questions

[SOLVED] Determine Whether Two Date Ranges Overlap

9 Answered Questions

[SOLVED] Parsing values from a JSON file?

  • 2010-05-14 15:54:20
  • michele
  • 2414383 View
  • 1329 Score
  • 9 Answer
  • Tags:   python json parsing

38 Answered Questions

[SOLVED] How to return only the Date from a SQL Server DateTime datatype

31 Answered Questions

[SOLVED] How to parse JSON in Java

  • 2010-04-07 09:00:21
  • Muhammad Maqsoodur Rehman
  • 1339309 View
  • 862 Score
  • 31 Answer
  • Tags:   java json parsing

16 Answered Questions

[SOLVED] Parse JSON in JavaScript?

35 Answered Questions

[SOLVED] Where can I find documentation on formatting a date in JavaScript?

2 Answered Questions

[SOLVED] DateFormat format method doesn't display a parsed date to a particular TimeZone

Sponsored Content