Home > Java | 日記2009前期 | 開発 > 月末日を求めるプログラム

月末日を求めるプログラム

検索すると結構見つかるものですが、JavaのCalendar#getActualMaximumを使った間違ったサンプルを多く見かけるので正しいやり方をメモメモ。相手の力量をはかるためのクイズとして使っても良いかもしれませんね。

カレンダーがgetInstance()じゃない事は言及しません。
以下は2006年2月の月末日を求めるコードです。

●とりあえず間違ったコード

GregorianCalendar c = new GregorianCalendar(Locale.JAPAN);
c.set(Calendar.YEAR, 2006);
c.set(Calendar.MONTH, 2 - 1);

System.out.println(c.getActualMaximum(Calendar.DAY_OF_MONTH));

何がいけないか。

月末に実行してみるとわかると思います。
仮に今日が2009年3月31日だとします。

まず1行目でCの値は2009年3月31日になります。(時間は省略)
次に2行目でCの値は2006年3月31日になります。
3行目でCの値は2006年2月31日になります。※
→2006年3月3日になります。
2006年3月の月末日は31日のため、31が表示されます。

というわけで、

●正しいコード

GregorianCalendar c = new GregorianCalendar(Locale.JAPAN);
c.set(Calendar.YEAR, 2006);
c.set(Calendar.MONTH, 2 - 1);
c.set(Calendar.DAY_OF_MONTH, 1);

System.out.println(c.getActualMaximum(Calendar.DAY_OF_MONTH));

Comments:2

Comment Form
なォ 2009年4月 2日 22:04

→2006年3月3日になります。
これにDAY_OF_MONTH1をセットしたら3月1日になってMAX31になると思ったんだけど実際28って出たからなんでかと思って
3行目の後ろに
System.out.println(c.get(Calendar.DAY_OF_MONTH));
っていれたら「3」って出て結果が31に変わるんだけどナゼナノ??
getした瞬間に2月31日が3月3日になるってこと?
おしえて先生!

タムタム 2009年4月 3日 01:59

Calendarは内部状態を色々持っているんですが、かなり端折って説明すると、
setをした時点では内容は確定しません。getした時に計算をするんです。
なので記事中の説明は正確ではないですね。

と書くと適当すぎるので、もうちょっと詳しく書くと、
isTimeSetというフラグがありまして、setするとこのisTimeSetのフラグが落ちます。
時間が不定という意味になるのですが、
getした時にcomplete() → isTimeSet==falseの場合に updateTime()を実行して値を確定させてフラグをふたたびたてます。

・setをすると値が不定になる
・getする時に値が不定だったら再計算をした上で返す。

確認するのであれば各ステップ毎にcを表示してみてください。

Trackbacks:0

TrackBack URL for this entry
Listed below are links to weblogs that reference
月末日を求めるプログラム from タムタムの日記

Home > Java | 日記2009前期 | 開発 > 月末日を求めるプログラム

Search
Feeds

Return to page top