0

Following code throws the exception when try to parse from the string (2011-12-08T02:01:02+01:00):

image.setLastUpdated(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz")
    .parse(imageElement.getAttribute("lastUpdate")))

I have also tried the following format:

image.setLastUpdated(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
    .parse(imageElement.getAttribute("lastUpdate")));

But I get the same exception:

java.text.ParseException: Unparseable date: "2011-12-08T02:01:02+01:00"
at java.text.DateFormat.parse(DateFormat.java:357)
at com.discavo.ImportManagerGiata.parseImageXML(ImportManagerGiata.java:204)
Jonathan
  • 20,053
  • 6
  • 63
  • 70
Ashish
  • 198
  • 3
  • 11

3 Answers3

5

You need X as the specifier for the UTC offset as it's in ISO-8601 format, as per the SimpleDateFormat documentation.

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX")
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Wonder how they got the name "SimpleDateFormat" through peer review! – Thorbjørn Ravn Andersen Dec 05 '13 at 14:45
  • Work, thanks a lot. I don't know how I overlooked the X option in java doc, but thanks! – Ashish Dec 05 '13 at 14:49
  • @ThorbjørnRavnAndersen At the time `SimpleDateFormat` was first added to Java, ISO-8601 was not widely used (maybe it didn't even exist yet). The `X` specifier was added in Java 7. – Jesper Dec 05 '13 at 14:55
  • 1
    @Jesper Actually the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard was published in the decade *prior* to Java's existence. And that style was in use in international business even earlier. The blame for poor date-time handling in Java belongs to the lack of research and thoughtfulness that went into the java.util.Date/Calendar classes. This part of the Java platform was rushed to market too early. Rectified by Joda-Time now and [JSR 310: Date and Time API](http://jcp.org/en/jsr/detail?id=310) soon in Java 8. – Basil Bourque Dec 06 '13 at 03:17
  • The `Z` specifier at least corresponds to *some* standard (RFC 822, according to the docs). But I agree that Java's `Date` and `Calendar` API is quite poor, and we should have had something like JSR-310 a long time ago... – Jesper Dec 06 '13 at 08:13
1

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Also, quoted below is a notice from the home page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Solution using java.time, the modern Date-Time API:

The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the Date-Time string conforms to the ISO 8601 standards. Your Date-Time string conforms to the ISO 8601 format.

Demo:

import java.time.Instant;
import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2011-12-08T02:01:02+01:00");
        System.out.println(odt);

        // ########### In case you need Instant ###########
        Instant instant = odt.toInstant();
        System.out.println(instant);
        
        // Java-12 onwards, you can parse the ISO-8601 compliant Date-Time with timezone
        // information directly into Instant
        instant = Instant.parse("2011-12-08T02:01:02+01:00");
        System.out.println(instant);
    }
}

Output:

2011-12-08T02:01:02+01:00
2011-12-08T01:01:02Z
2011-12-08T01:01:02Z

ONLINE DEMO

An Instant represents an instantaneous point on the timeline in UTC. The Z in the output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Note: For any reason, if you need to convert this object of Instant to an object of java.util.Date, you can do so as follows:

Date date = Date.from(instant);

Learn more about the modern Date-Time API from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

The answer by Jon Skeet is correct. But FYI…

No problem in Joda-Time

The problem presented by this question does not exist if using Joda-Time rather than the mess that is the java.util.Date/Calendar classes bundled with Java.

Joda-Time 2.3 has a variety of built-in parsers, so no need to specify a format in this case. Use methods on the ISODateTimeFormat class to retrieve a variety of formatters designed to parse variations of ISO 8601 formatted strings.

The question fails to account for time zone. So I am showing all three possibilities:

  • You want the time converted to a specific time zone.
    Denver in this example.
  • You want the time adjusted to UTC, for no time offset.
    Common for storage or further date-time work.
  • You want to preserve this date-time with its offset.
    Not usually a good idea, as you have neither the benefit of UTC (no offset and no need to worry about Daylight Saving Time DST or other issues), nor the benefit of a named time zone with rules to handle DST or other issues.

For Desired Time Zone

// For desired time zone. Arbitrarily using 'Denver' as named time zone for this example.
DateTimeZone denverTimeZone = DateTimeZone.forID( "America/Denver" );
org.joda.time.DateTime dateTimeInDenver = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis().withZone(denverTimeZone).parseDateTime( "2011-12-08T02:01:02+01:00" );
System.out.println( "dateTimeInDenver: " + dateTimeInDenver );

When run…

dateTimeInDenver: 2011-12-07T18:01:02.000-07:00

For UTC

// For UTC (no offset).
org.joda.time.DateTime dateTimeInUTC = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis().withZoneUTC().parseDateTime( "2011-12-08T02:01:02+01:00" );
System.out.println( dateTimeInUTC );

When run…

2011-12-08T01:01:02.000Z

For Offset As Parsed

// For offset as parsed. 
// Least beneficial, as no rules for Daylight Saving Time (DST) or other anomalies can be applied.
org.joda.time.DateTime dateTimeWithOffsetParsed = org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed().parseDateTime( "2011-12-08T02:01:02+01:00" );
System.out.println( "dateTimeWithOffsetParsed: " + dateTimeWithOffsetParsed );

When run…

dateTimeWithOffsetParsed: 2011-12-08T02:01:02.000+01:00
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154