Javaと情熱のあいだ

カステラとドーナツと珈琲

Joda-TimeのparseDateTime

Javaの日時関連クラスの代替ライブラリ「Joda-Time 1.5」リリース
Joda-Timeを使ってみた、結構使えるかも。
日付関連の処理が充実してるしDate、Calendarから開放されそう。
ひとつだけ気に入らないのが日付パーサ関連のクラス。

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy/MM/dd");
        
System.out.println(formatter.parseDateTime("2007/11/01"));

2007-11-01T00:00:00.000+09:00
と出力されるけどなんか、使いにくい・・・。
DateTimeFormatterBuilderも使って変換してみるけれど微妙。
Jakarta commons LongのDateUtils.parseDateを参考にDateTimeUtilsクラスを拡張して
日付パーサを強化してみる。

import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeParserBucket;

/**
 * <HR>
 * <P>
 *  ■モジュール名 <BR>
 * <BLOCKQUOTE>
 *      DateTimeUtilsEx.java <BR>
 * </BLOCKQUOTE>
 * <P>
 *  ■クラス仕様 <BR>
 * <BLOCKQUOTE>
 *      DateTimeUtilsExクラスはDateTimeUtilsの拡張クラスです。<BR>
 * </BLOCKQUOTE>
 * <P>
 * <HR>
 * <P>
 */
public class DateTimeUtilsEx extends DateTimeUtils{

    /**
     * 日付フォーマット
     */
    private static String[] parsePatterns = {"yyyy/MM/dd","yyyyMMdd"};

    /**
     *
     * 日付パーサ、フォーマット内包
     * @param str
     * @return 
     */
    public static DateTime parseDateTime(String str) {
        return parse(str, parsePatterns);
    }

    /**
     *
     * 日付パーサ、複数フォーマット指定
     * @param str
     * @return
     */
    public static DateTime parseDateTime(final String str
            , final String[] parsePatterns) {
        return parse(str, parsePatterns);
    }

    /**
     *
     * 日付パーサ、単フォーマット指定
     * @param str
     * @return
     */
    public static DateTime parseDateTime(final String str
            , final String parsePattern) {
        return parse(str, new String[]{parsePattern});
    }

    /**
     *
     * 日付パーサ実行
     * @param str
     * @param parsePatterns
     * @return
     */
    private static DateTime parse(final String str
            , final String[] parsePatterns) {

        if (str == null || parsePatterns == null) {
            throw new IllegalArgumentException(
                    "Date and Patterns must not be null");
        }

        DateTimeFormatter formatter;

        DateTimeParserBucket bucket;

        int newPos = -1;

        for (int i = 0; i < parsePatterns.length; i++) {

            formatter = DateTimeFormat.forPattern(parsePatterns[i]);

            bucket = new DateTimeParserBucket(0, formatter.getChronolgy()
                    , formatter.getLocale(), formatter.getPivotYear());

            newPos = formatter.getParser().parseInto(bucket, str, 0);
            if (newPos >= 0) {
                if (newPos >= str.length()) {
                    final long millis = bucket.computeMillis(true, str);
                    return new DateTime(millis, formatter.getChronolgy());
                }
            }
            else {
                newPos = ~newPos;
            }

        }
        throw new IllegalArgumentException(createErrorMessage(str, newPos));
    }

    /**
     *
     * エラーメッセージ作成。
     * @param text
     * @param errorPos
     * @return
     */
    private static String createErrorMessage(final String text
            , final int errorPos) {
        int sampleLen = errorPos + 32;
        String sampleText;
        if (text.length() <= sampleLen + 3) {
            sampleText = text;
        } else {
            sampleText = text.substring(0, sampleLen).concat("...");
        }

        if (errorPos <= 0) {
            return "Invalid format: \"" + sampleText + '"';
        }

        if (errorPos >= text.length()) {
            return "Invalid format: \"" + sampleText + "\" is too short";
        }

        return "Invalid format: \"" + sampleText + "\" is malformed at \"" +
            sampleText.substring(errorPos) + '"';
    }

}

呼び出し側はこんなかんじ

DateTime dateTime = DateTimeUtilsEx.parseDateTime("20071101"
        , new String[]{"yyyy/MM/dd","yyyyMMdd"});

System.out.println(dateTime);

dateTime = DateTimeUtilsEx.parseDateTime("2007/11/01");

System.out.println(dateTime);

dateTime = DateTimeUtilsEx.parseDateTime("20071101", "yyyyMMdd");

System.out.println(dateTime.toDate());

この三つあればどんな日付でも変換可能。