35

I could not find this anywhere. I fetch some JSON from an API that returns standard JSON dates. You can see the format by running this code in a JavaScript console:

> new Date().toJSON();
"2010-10-27T11:58:22.973Z"

Well, actually, the API I'm working with is not returning the millisecond part, and sometimes it returns a timezone instead of Z, so dates can look like any one of these:

  • 2010-10-27T11:58:22Z
  • 2010-10-27T11:58:22+03:00

Parsing these kinds of dates is somewhat cumbersome. Is there any way to parse these kinds of dates, using org.json?

My current solution is:

public static Date parseDateTime(String dateString) {
    if (dateString == null) return null;
    DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
    if (dateString.contains("T")) dateString = dateString.replace('T', ' ');
    if (dateString.contains("Z")) dateString = dateString.replace("Z", "+0000");
    else
        dateString = dateString.substring(0, dateString.lastIndexOf(':')) + dateString.substring(dateString.lastIndexOf(':')+1);
    try {
        return fmt.parse(dateString);
    }
    catch (ParseException e) {
        Log.e(Const.TAG, "Could not parse datetime: " + dateString);
        return null;
    }
}

Ugh!

Felix
  • 88,392
  • 43
  • 149
  • 167
  • In a comment below, you mentioned that you're implementing for Android. Did you try Android `SimpleDateFormat`'s `ZZZZZ`? – class stacker Oct 14 '15 at 13:42

3 Answers3

20

That DateTime format is actually ISO 8601 DateTime. JSON does not specify any particular format for dates/times. If you Google a bit, you will find plenty of implementations to parse it in Java.

Here's one

If you are open to using something other than Java's built-in Date/Time/Calendar classes, I would also suggest Joda Time. They offer (among many things) a ISODateTimeFormat to parse these kinds of strings.

codelark
  • 12,254
  • 1
  • 45
  • 49
  • +1 for the Joda time recommendation – Gary Oct 27 '10 at 12:23
  • Hmm, interesting. Their solution is pretty similar to mine :). It's weird that Java doesn't have this built-in, if it's standard. – Felix Oct 27 '10 at 12:26
  • As for Joda Time, my project is on Android and I want to use as little external libs as possible. Thanks for the tip, though. – Felix Oct 27 '10 at 12:28
  • As with @Felix , I have a requirement to send a JSON date (i.e. "2011-06-29T14:00:42.289Z") to Java and parse it. I also don't want to use too many libraries. Is there any advantage to the Joda library if my requirement seems to be met by the [ISO8601DateParser](http://www.java2s.com/Code/Java/Data-Type/ISO8601dateparsingutility.htm) class, that @codelark linked to? – blong Jun 29 '11 at 14:00
  • @blong I cannot see how the [ISO8601DateParser](http://www.java2s.com/Code/Java/Data-Type/ISO8601dateparsingutility.htm) is doing any good. With Java 7, you have the `X` time zone format letter. Apart from that, the rest of `SimpleDateFormat` is not fully ISO 8601 compliant, because it will not output negative year numbers but rather stick to its idea of the "era". One has to format the year separately for ISO 8601 compliance before for dates prior to year 1; similar for scanning (also note the year number difference between `SimpleDateFormat` and ISO 8601). – class stacker Oct 14 '15 at 13:35
  • @ClassStacker I appreciate the comment (I'm sure other googlers will too). However, this question was asked in 2010 and my comment is from June 2011 (about 1 month before Java 7's release date). – blong Oct 15 '15 at 12:40
14

Note that SimpleDateFormat format pattern Z is for RFC 822 time zone and pattern X is for ISO 8601 (this standard supports single letter time zone names like Z for Zulu).

So new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX") produces a format that can parse both "2013-03-11T01:38:18.309Z" and "2013-03-11T01:38:18.309+0000" and will give you the same result.

Unfortunately, as far as I can tell, you can't get this format to generate the Z for Zulu version, which is annoying.

I actually have more trouble on the JavaScript side to deal with both formats.

Chuck
  • 1,850
  • 2
  • 17
  • 28
7

If you need to support more than one format you will have to pattern match your input and parse accordingly.

final DateFormat fmt;
if (dateString.endsWith("Z")) {
    fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
} else {
    fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
}

I'd guess you're dealing with a bug in the API you're using which has quoted the Z timezone date pattern somewhere...

Jon Freedman
  • 9,469
  • 4
  • 39
  • 58
  • 1
    The literal Z is valid - it's another way of saying `+00:00`, i.e. UTC time. It stands for 'zulu': _"...also colloquially referred to as "Zulu Time", particularly in the United States military..."_ ([Wikipedia](http://en.wikipedia.org/wiki/Coordinated_Universal_Time)) – Mark Embling Jul 14 '11 at 18:04