Hello,
I have just discovered that joda does not parse datetimes that contain
timezones. Hence I am forced to use the date parsing routines in
java.util. But they do not seem to handle bad dates. For example,
2008-13-01 parses as if it was 2008-01-01. I can even give it the 30th
of February and it says ths is ok!
What do people use to parse datetimes please? I am looking for
something that will not accept invalid dates and that handles
timezones, whether specified as timezone name or offset from UTC (as
per ISO 8601).
Regards,
Andrew Marlow
The example test program below shows some of the problems encountered
by using the Joda DateTime with explicit use of the ISOChronology.
Hopefully this will satisify the sckeptics that there is indeed a
problem with joda datetimes and ISO8601. Note that the program uses
the ISO chronology rather than a datetime formatter because the
formatter does not cover all ISO8601 cases and is documented as not
working properly wrt timezones.
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.chrono.ISOChronology;
public class Iso8601Test {
public void test() {
checkDateTime("2009-06-30T13:45:04", 2009, 6, 30, 13, 45,
4);
// with GMT offsets
checkDateTimeWithOffset("2009-06-30T13:45:04+00:00", 2009, 6,
30, 13, 45, 4, 0);
checkDateTimeWithOffset("2009-06-30T13:45:04+01:00", 2009, 6,
30, 13, 45, 4, 1);
checkDateTimeWithOffset("2009-06-30T13:45:04+05:00", 2009, 6,
30, 13, 45, 4, 5);
checkDateTimeWithOffset("2009-06-30T13:45:04+09:00", 2009, 6,
30, 13, 45, 4, 9);
checkDateTimeWithOffset("2009-06-30T13:45:04-03:00", 2009, 6,
30, 13, 45, 4, -3);
checkDateTimeWithOffset("2009-06-30T13:45:04-07:00", 2009, 6,
30, 13, 45, 4, -7);
// bad dates
checkBadStrings("2009-13-30T13:45:04", 2009, 6, 30, 13, 45,
4);
checkBadStrings("2009-02-30T13:45:04", 2009, 6, 30, 13, 45,
4);
}
private void checkDateTime(String dateTimeString,
int yyyy, int mm, int dd,
int hh, int mi, int ss) {
DateTime actualDateTime = new DateTime(dateTimeString,
ISOChronology.getInstance());
DateTime expectedDateTime = new DateTime(yyyy, mm, dd, hh, mi,
ss, 0);
if (actualDateTime.equals(expectedDateTime)) {
System.out.println(String.format("ok, input string = '%s',
converted datetime = %s\n",
dateTimeString,
actualDateTime));
} else {
System.out.println(String.format("failed to convert
properly, input string = '%s'\n"
+ "converted value = %s\n", dateTimeString,
actualDateTime));
}
}
private void checkDateTimeWithOffset(String dateTimeString,
int yyyy, int mm, int dd,
int hh, int mi, int ss, int
offset) {
DateTime actualDateTime = new DateTime(dateTimeString,
ISOChronology.getInstance());
DateTimeZone dateTimeZone = DateTimeZone.forOffsetHours
(offset);
DateTime expectedDateTime = new DateTime(yyyy, mm, dd,
hh, mi, ss, 0,
dateTimeZone);
if (actualDateTime.equals(expectedDateTime)) {
System.out.println(String.format("ok, input string = '%s',
converted datetime = %s\n",
dateTimeString,
actualDateTime));
} else {
System.out.println(String.format("failed to convert
properly, offset = %s, input string = '%s'\n"
+ " converted value = '%s'\n"
+ " expected value = '%s'\n", offset,
dateTimeString, actualDateTime, expectedDateTime));
}
}
public void checkBadStrings(String dateTimeString,
int yyyy, int mm, int dd,
int hh, int mi, int ss) {
try {
DateTime actualDateTime = new DateTime(dateTimeString,
ISOChronology.getInstance());
throw new RuntimeException(String.format("parsed string
'%s' as '%s' when should have got exception", dateTimeString,
actualDateTime));
} catch (org.joda.time.IllegalFieldValueException exception) {
System.out.println("correctly encountered exception for
bad string");
}
}
public static void main(String[] args) {
Iso8601Test app = new Iso8601Test();
app.test();
System.exit(0);
}
}