2016年2月29日月曜日

Javaで月末を取得しようとすると2月31日が取得される不具合について。

Java 月末 というキーワードで検索をすると以下の様なソースコードが見つかります。
1月なら31日、2月なら28日か29日を取得したい場合に使います。


実はこの実装だと29日以降に動かすと2月31日という値が返ってきます。
つまりある時期だけ不具合が出るという危険なコードです。

/**
 * 指定した日付文字列(yyyy/MM/dd or yyyy-MM-dd)
 * における月末日付を返します。
 * 
 * @param strDate 対象の日付文字列
 * @return 月末日付
 */
public static int getLastDay(String strDate) {
    int yyyy = Integer.parseInt(strDate.substring(0,4));
    int MM = Integer.parseInt(strDate.substring(5,7));
    int dd = Integer.parseInt(strDate.substring(8,10));
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, yyyy);
    cal.set(Calendar.MONTH, MM);
    int last = cal.getActualMaximum(Calendar.DATE);
    return last;
}
getInstanse()は実行日時が影響します。
29日に実行すると、cal.set(Calendar.MONTH, MM);の部分で2月の場合、2月29日となり、3月1日になります。そして3月の末日の31日がリターンされます。

この解消法は、以下のようにcal.clear();を入れることです。

/**
 * 指定した日付文字列(yyyy/MM/dd or yyyy-MM-dd)
 * における月末日付を返します。
 * 
 * @param strDate 対象の日付文字列
 * @return 月末日付
 */
public static int getLastDay(String strDate) {
    int yyyy = Integer.parseInt(strDate.substring(0,4));
    int MM = Integer.parseInt(strDate.substring(5,7));
    int dd = Integer.parseInt(strDate.substring(8,10));
    Calendar cal = Calendar.getInstance();
    cal.clear();
    cal.set(Calendar.YEAR, yyyy);
    cal.set(Calendar.MONTH, MM);
    int last = cal.getActualMaximum(Calendar.DATE);
    return last;

}

0 件のコメント: