- ベストアンサー
java.util.Calendar クラスの add メソッドについて
APIドキュメントの Calendar クラスの解説のところに、 //------------------------------------------------------------------ Add rule 2。小さいフィールドが不変式であると予想される場合に、フィールド f が変更されてから最小値または最大値が変更されたために、その前の値と等しくならないと、フィールドの値はその予想される値にできるだけ近くなるように調整されます。小さいフィールドは、小さい時間の単位を表します。HOUR は、DAY_OF_MONTH よりも小さいフィールドです。不変式ではないと予想される小さいフィールドは、調整されません。カレンダシステムでは、不変式であると予想されるフィールドが判断されます。 //------------------------------------------------------------------ という記述がありますが、何のことかさっぱりわかりません。 いろいろ試しましたが、add メソッドが直感に反する振舞いをすることは ありませんでした。 こういうコードを書くと、add メソッドが変な動きをするよ、というのが あったら教えてください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
> 不変式ではないと予想される小さいフィールドは、調整されません。 > > という一文があるのが気になってます。 > 調整されない、というのはどういうことで、 > 具体的にどういうときに起こるものなんでしょうか。 > それとも何か、考え方が根本的に間違ってるんでしょうか。 javadocにあるとおり、addメソッドで月を変更しても、より小さい不変式ではないと予想されるフィールド(DAY_OF_YEARやDAY_OF_WEEK)が再計算されないことを意味します。 ここで問題になるのが、Calendarクラスのgetメソッドです。 (GregorianCalendarはオーバーライドしていないので同じもの) addメソッドの中では不変式フィールド(YEARやMONTHなど)については再計算していますが、不変式ではないDAY_OF_WEEKなどは再計算されていません。 が、実際はgetメソッドの中でこれらの値を補正するための関数(abstract指定されているので、実際はGregorianCalendarの中の関数)で補正しなおしています。 > いろいろ試しましたが、add メソッドが直感に反する振舞いをすることは > ありませんでした。 上記のような理由から、getメソッドが呼ばれると自動的に補正されます。 このため、例えば以下のようなソースを記述します。 import java.util.GregorianCalendar; public class CalendarDemo extends GregorianCalendar { public CalendarDemo(int year, int month, int day) { super(year, month, day); } public int myGet(int field) { return internalGet(field); } } このクラスでは、フィールドの値を取得するときに、補正を行わずに取得します。そして、addメソッドで月のフィールドに値を加算し、myGetメソッドでDAY_OF_YEARなどを取得すると、見事に補正されない値が返されているのが分かります。。。 public void met() { CalendarDemo cal = new CalendarDemo(2001, 0, 1); GregorianCalendar cal2 = new GregorianCalendar(2001, 0, 1); cal.add(Calendar.MONTH, 9); cal2.add(Calendar.MONTH, 9); System.out.println( "DAY_OF_YEAR(Demo) : " + cal.myGet(Calendar.DAY_OF_YEAR) ); System.out.println( "DAY_OF_YEAR(Greg) : " + cal2.get( Calendar.DAY_OF_YEAR ) ); System.out.println( "DATE(Demo) : " + cal.myGet(Calendar.DATE) ); System.out.println( "DATE : " + cal2.get( Calendar.DATE ) ); System.out.println( "CalendarDemo = " + cal.getTime().toString() ); System.out.println( "GregorianCalendar = " + cal2.getTime().toString() ); } Calendarクラスを利用するプログラムでは、getメソッドを使わずにフィールドにアクセスすることは不可能(フィールドがprotected intだから)なので問題になることはないようです。 ただし、サブクラスを作るような場合には、上記の条件の影響を受ける可能性がありますので、注意が必要ということになります。
その他の回答 (2)
- ranx
- ベストアンサー率24% (357/1463)
> 不変式ではないと予想される小さいフィールドは、調整されません。 > という一文があるのが気になってます。 > 調整されない、というのはどういうことで、 > 具体的にどういうときに起こるものなんでしょうか。 これも例が載っていますね。 日付は月を増減させても通常は変わらないことが期待されているのですが、 ルールを適用して変更することがあります。 曜日は月を増減させると変わるのが当たり前なので、調整の対象とはなりません。 ・・・って、オイ、どうなるんだこれ?やってみよう。
- ranx
- ベストアンサー率24% (357/1463)
その下に例が載っていると思いますが。 例えば、8月31日に8ヶ月を加えると4月31日になりますけど、 そんな日はないので自動的に調整して4月30日にしますということですね。 ところで、Calendarはabstractクラスなので、実装によって動作が変わります。 (変わりえます。)まあ、普通はGregorianCalendarでしょうけれど。
補足
回答ありがとうございます。 直感に反する、という言い方は曖昧でしたが、 4月31日が30日に自動的に調整される、というのは自分的には わかりやすい振舞いだと思います。 調整されるのが問題なのではなく、下のほうに、 不変式ではないと予想される小さいフィールドは、調整されません。 という一文があるのが気になってます。 調整されない、というのはどういうことで、 具体的にどういうときに起こるものなんでしょうか。 それとも何か、考え方が根本的に間違ってるんでしょうか。 > ところで、Calendarはabstractクラスなので、実装によって動作が変わります。 >(変わりえます。)まあ、普通はGregorianCalendarでしょうけれど。 これは理解してます。 GregorianCalendar での実装について話をしているつもりです。
お礼
回答ありがとうございます。 とてもよくわかりました。 Calendarクラス、本格的に使う機会があるかわかりませんが、 この一連のQAはかなり勉強になりました。 また質問したときはよろしくおねがいします。