I am trying to convert an ISO 8601 formatted String to a java.util.Date
.
I found the pattern yyyy-MM-dd'T'HH:mm:ssZ
to be ISO8601-compliant if used with a Locale (compare sample).
However, using the java.text.SimpleDateFormat
, I cannot convert the correctly formatted String 2010-01-01T12:00:00+01:00
. I have to convert it first to 2010-01-01T12:00:00+0100
, without the colon.
So, the current solution is
SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));
which obviously isn't that nice. Am I missing something or is there a better solution?
Answer
Thanks to JuanZe's comment, I found the Joda-Time magic, it is also described here.
So, the solution is
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));
Or more simply, use the default parser via the constructor:
DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;
To me, this is nice.
The DatatypeConverter solution doesn't work in all VMs. The following works for me:
I've found that joda does not work out of the box (specifically for the example I gave above with the timezone on a date, which should be valid)
Do it like this:
Here is the output:
Wed Oct 19 15:15:36 CST 2016
The Jackson-databind library also has ISO8601DateFormat class that does that (actual implementation in ISO8601Utils.
Also you can use the following class -
Link to the Java Doc - Hierarchy For Package org.springframework.extensions.surf.maven.plugin.util
The workaround for Java 7+ is using SimpleDateFormat:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
This code can parse ISO8601 format like:
2017-05-17T06:01:43.785Z
2017-05-13T02:58:21.391+01:00
But on Java6,
SimpleDateFormat
doesn't understandX
character and will throwIllegalArgumentException: Unknown pattern character 'X'
We need to normalize ISO8601 date to the format readable in Java 6 with
SimpleDateFormat
.Method above to replace [
Z
with+0000
] or [+01:00
with+0100
] when error occurs in Java 6 (you can detect Java version and replace try/catch with if statement).tl;dr
Using java.time
The new java.time package in Java 8 and later was inspired by Joda-Time.
The
OffsetDateTime
class represents a moment on the timeline with an offset-from-UTC but not a time zone.Calling
toString
generates a string in standard ISO 8601 format:To see the same value through the lens of UTC, extract an
Instant
or adjust the offset from+01:00
to00:00
.…or…
Adjust into a time zone if desired. A time zone is a history of offset-from-UTC values for a region, with a set of rules for handling anomalies such as Daylight Saving Time (DST). So apply a time zone rather than a mere offset whenever possible.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
,Calendar
, &SimpleDateFormat
.The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for
java.sql.*
classes.Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as
Interval
,YearWeek
,YearQuarter
, and more.