// split 2007-12-19T10:20:30.789+0500 into its parts
// correct: yyyy['-'MM['-'dd['T'HH':'MM[':'ss['.'SSS]]('Z'|ZZZZZ)]]]
final StringTokenizer t = new StringTokenizer(s, "-T:.Z+", true);
if (s == null || t.countTokens() == 0)
throw new ParseException("parseISO8601: Cannot parse '" + s + "'", 0);
try {
// year
cal.set(Calendar.YEAR, Integer.parseInt(t.nextToken()));
// month
if (t.nextToken().equals("-")) {
cal.set(Calendar.MONTH, Integer.parseInt(t.nextToken()) - 1);
} else {
return cal.getTime();
}
// day
if (t.nextToken().equals("-")) {
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(t.nextToken()));
} else {
return cal.getTime();
}
// The standard says:
// if there is an hour there has to be a minute and a timezone token, too.
if (t.nextToken().equals("T")) {
final int hour = Integer.parseInt(t.nextToken());
// no error, got hours
int min = 0;
int sec = 0;
int msec = 0;
if (t.nextToken().equals(":")) {
min = Integer.parseInt(t.nextToken());
// no error, got minutes
// need TZ or seconds
String token = t.nextToken();
if (token.equals(":")) {
sec = Integer.parseInt(t.nextToken());
// need millisecs or TZ
token = t.nextToken();
if (token.equals(".")) {
msec = Integer.parseInt(t.nextToken());
// need TZ
token = t.nextToken();
}
}
// check for TZ data
int offset;
if (token.equals("Z")) {
offset = 0;
} else {
int sign = 0;
if (token.equals("+")) {
sign = 1;
} else if (token.equals("-")) {
sign = -1;
} else {
// no legal TZ offset found
return cal.getTime();
}
offset = sign * Integer.parseInt(t.nextToken()) * 10 * 3600;
}
cal.set(Calendar.ZONE_OFFSET, offset);
}
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, min);
cal.set(Calendar.SECOND, sec);
cal.set(Calendar.MILLISECOND, msec);
}
} catch (final NoSuchElementException e) {
// ignore this as it is perfectly fine to have non-complete date in this format
} catch (final Exception e) {
// catch all Exceptions and return what we parsed so far
//serverLog.logInfo("SERVER", "parseISO8601: DATE ERROR with: '" + s + "' got so far: '" + cal.toString());
}
// in case we couldn't even parse a year
if (!cal.isSet(Calendar.YEAR))
throw new ParseException("parseISO8601: Cannot parse '" + s + "'", 0);
Date d = cal.getTime();
return d;
}