ISO8601 in Java

ISO8601 文字列というのは、日付の表現方法で

  • 2008-01-18T00:35:45.123+09:00
  • 2008-01-18T00:35:45+09:00
のように、XML フィードでよく見かけるものです。ISO8601:2004 が最新の仕様で、日付、時刻、タイムゾーン、期間などが定義されています。

Javajava.text.SimpleDateFormat では、


SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
System.out.println(sdf.format(new Date));
で "2008-01-18T00:35:45.123+0900" のように、+09:00 ではなく +0900 となり、

String dateStr = "2008-01-18T00:35:45.123+09:00";
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
try {
java.util.Date date = sdf.parse(dateStr);
} catch (java.text.ParseException e) {
e.printStackTrace();
}
ParseException となってしまいます。SimpleDateFormat が ISO8601 に対応していないのが現在の仕様ということです。

org.apache.commons.lang.time の FastDateFormat で +0900 と +09:00 とを扱えますが、今回は用途が限定されていたので、


private static final java.text.SimpleDateFormat DATE_FORMAT_MILLIS_ISO8601 =
new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
private static final String REGEX_DATE_FORMAT_MILLIS_ISO8601 =
"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}[-+]\\d{2}:\\d{2}";

    java.util.Date date = null;
    if (dateString.matches(REGEX_DATE_FORMAT_MILLIS_ISO8601)) {
        int index = dateString.lastIndexOf(":");
        StringBuffer sb = new StringBuffer(dateString).deleteCharAt(index);
        try {
            date = DATE_FORMAT_MILLIS_ISO8601.parse(sb.toString());
        } catch (java.text.ParseException e) {
        }
    }

としてみました。

Commons LangJoda Time などのライブラリを使うことになりそうです。

JSR 310: Date and Time API にて、Java の日付まわりの問題は整理されますが、Java SE 7 待ちです。

森田