1

I'd like to use Joda-Time to parse a date with an optional timezone: 2014-08-08+02:00

I tried ISODateTimeFormat.dateTimeParser().parseDateTime(date); but that gives me the following error:

java.lang.IllegalArgumentException: Invalid format: "2014-08-08+02:00" is malformed at "+02:00"

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • I think you're missing a `T` between the date and the offset. – Duncan Jones Jun 30 '14 at 12:16
  • Definitely not as I want to *parse* this string (I don't generate the string myself, otherwise I could just directly create the joda date) – membersound Jun 30 '14 at 12:17
  • Ok, well interpret my comment to mean "*You'd need a `T` there if you intend to use that parser*". I suspect you'll have to define your own - try looking at this for inspiration: [How can I parse a date including timezone with Joda Time](http://stackoverflow.com/questions/1327229/how-can-i-parse-a-date-including-timezone-with-joda-time?rq=1). – Duncan Jones Jun 30 '14 at 12:18
  • Oh ok, I thought joda is capable to detect the format self. – membersound Jun 30 '14 at 12:18
  • 2
    I'm not a Joda expert - perhaps someone can help you find something that does it automatically. But the Javadocs for `ISODateTimeFormat.dateTimeParser()` are quite clear on what is accepted, and your string isn't. – Duncan Jones Jun 30 '14 at 12:19
  • What does it mean to have a date (year/month/day) and a timezone but no time? – Brett Okken Jun 30 '14 at 12:26
  • I don't know what the purspose of this is, but the webservice API returns it and I want to parse it. I don't care why they are giving me that format. So I'll probably just cut the timezone off and work with the date. – membersound Jun 30 '14 at 12:27
  • No, **do not ignore offset** if you want to work with a date-time value (a date plus a time-of-day). The time of day will be set to first moment of day (usually 00:00:00) for specified/default time zone. But you want that time-of-day adjusted to two hours ahead of UTC. Even if you want a LocalDate, the offset is used in construction to determine whether you mean tomorrow in Paris or yesterday in New York (for example). – Basil Bourque Jun 30 '14 at 14:02

2 Answers2

3

I'm not aware of a better way to handle optional data than to have several patterns and parse them in turn. See code example below:

public static void main(String[] args) throws Exception {
  System.out.println(parseWithOptionalTZ("2014-08-08+02:00"));
  System.out.println(parseWithOptionalTZ("2014-08-08"));
}

private static DateTime parseWithOptionalTZ(String date) {
  DateTimeFormatter[] formatters = { 
      DateTimeFormat.forPattern("YYYY-MM-dd"),
      DateTimeFormat.forPattern("YYYY-MM-ddZ") 
  };

  for (DateTimeFormatter dateTimeFormatter : formatters) {
    try {
      return dateTimeFormatter.parseDateTime(date);
    } catch (IllegalArgumentException e) {
      // ignore
    }
  }

  throw new IllegalArgumentException("Could not parse: " + date);
}

Output:

2014-08-07T23:00:00.000+01:00
2014-08-08T00:00:00.000+01:00
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
2

Time Zone Is Crucial

Do not ignore the time zone or offset, as mentioned in the comments.

Ignoring time zone on a date-time is like ignoring the C/F (Celsius/Fahrenheit) on a temperature reading or ignoring the character set encoding of text. You will be misinterpreting your data.

Parsing With Time Zone

Specifying a time zone during parsing can have two different effects in Joda-Time. Mull this over and you’ll realize it is logical and is doing the right thing.

After Parsing

If you specify a time zone on a formatter that parses an input containing an offset or time zone, then Joda-Time pays attention to the contained offset during the parsing. After the date-time is determined (where it falls on the timeline of the Universe defined as number of milliseconds since the beginning of 1970 in UTC time zone, that is, no time zone), then your specified time zone is assigned to the DateTime object. In this case, passing the specified time zone did not affect the parsing. The specified time zone affects the generation of String representations of that date-time value.

During Parsing

If, on the other hand, you specify a time on a formatter that parses an input lacking any offset or time zone information, then Joda-Time uses your specified time zone during the parsing of the input String.

Example Code, Joda-Time

Here is example code using Joda-Time 2.3. First is the right way, using the offset during parsing of the string. Second is the wrong way, ignoring the offset. Notice the different results, different date-time values, even possibly different dates (depending on the time zone used to create String representations).

With Offset

String input = "2014-08-08+02:00";
DateTimeFormatter formatter = DateTimeFormat.forPattern( "yyyy-MM-ddZ" ).withZone( DateTimeZone.UTC );
DateTime dateTimeUsingOffset = formatter.parseDateTime( input ); // Offset used to determine date-time during parsing. After parsing the UTC time zone is assigned.

Without Offset

String inputTruncatedOffset = input.substring( 0, 10 );
DateTime dateTimeIgnoringOffset = new DateTime( inputTruncatedOffset, DateTimeZone.UTC ); // In contrast to above, the UTC time zone is used *during* parsing to determine date-time as the input string contained no hint about offset or time zone.

Dump to console.

System.out.println( "input: " + input );
System.out.println( "dateTimeUsingOffset: " + dateTimeUsingOffset );

System.out.println( "inputTruncatedOffset: " + inputTruncatedOffset );
System.out.println( "dateTimeIgnoringOffset: " + dateTimeIgnoringOffset );

When run.

input: 2014-08-08+02:00
dateTimeUsingOffset: 2014-08-07T22:00:00.000Z

inputTruncatedOffset: 2014-08-08
dateTimeIgnoringOffset: 2014-08-08T00:00:00.000Z
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154