(編集して申し訳ありませんが、これをもう少し読みやすくしたかったのですが、最初に答えを書いたときに正しく理解できませんでした...今はエッセイの長さですが、そこに行きます...)
すでに述べたことに加えて、問題は、返されたCalendar
インスタンスが異なる方法で準備されていることから発生します。個人的にはこれは設計上の欠陥だと思いますが、それには十分な理由があるかもしれません。
を呼び出すと、デフォルトのコンストラクターを使用しCalendar.getInstance()
て新しいコンストラクターが作成されます。GregorianCalendar
このコンストラクターはsetCurrentTimeMillis(time)
、現在のシステム時刻で呼び出してから、保護されたメソッドを呼び出しますcomplete()
。
GregorianCalendar
ただし、作成したコンストラクターを使用して新しいものを作成すると、complete()
が呼び出されることはありません。代わりに、とりわけ、set(field, value)
提供されるさまざまな情報に対してのみ呼び出されます。これはすべてうまくいっていますが、いくつかの紛らわしい結果があります。
最初のケースでが呼び出されると、 dustmachinecomplete()
がほのめかしているメンバー変数がチェックされ、再計算する必要のある情報が決定されます。これにより、すべてのフィールド(、、など)の計算を強制するブランチが生成されDAY
ますWEEK_OF_MONTH
。Calendar
それは確かに怠惰であることに注意してください。このインスタンス化の方法を使用すると、その場で明示的な再計算(またはこの場合は初期計算)が強制されることがあります。
では、これはどのような影響を及ぼしますか?2番目のオブジェクト作成の場合、事前のフィールド計算が実行されなかったことを考えると、2つのオブジェクトの状態は大きく異なります。1つ目はすべてのフィールド情報が入力され、2つ目は指定した情報のみが含まれます。さまざまなメソッドを呼び出す場合get*()
、情報を取得するときに変更を加えると遅延再計算ステップが発生するため、問題はありません。ただし、この再計算が発生する順序により、2つの異なる初期状態の違いが明らかになります。
あなたの特定のケースでは、これは次の関連するコードが原因です。これは、次のコマンドcomputeTime()
で要求したときに正しい時間を計算するために必ず呼び出されますgetTime()
。
boolean weekMonthSet = isSet[WEEK_OF_MONTH] || isSet[DAY_OF_WEEK_IN_MONTH];
...
boolean useDate = isSet[DATE];
if (useDate && (lastDateFieldSet == DAY_OF_WEEK
|| lastDateFieldSet == WEEK_OF_MONTH
|| lastDateFieldSet == DAY_OF_WEEK_IN_MONTH)) {
useDate = !(isSet[DAY_OF_WEEK] && weekMonthSet);
}
最初のケースでは、その初期計算のためにすべてのフィールドが設定されます。これにより、trueが可能になり、 setの呼び出しで指定したものweekMonthSet
とともに、falseになります。DAY_OF_WEEK
set(field, value)
useDate
set(field, value)
ただし、2番目のケースでは、フィールドが計算されていないため、設定されるフィールドは、コンストラクターと後続の呼び出しで指定したフィールドのみです。したがって、コンストラクターごとにuseDate
trueであるため、trueのままになりますが、オブジェクト内の他のフィールドはどこにも計算されておらず、ユーザーによって設定されていないため、falseになります。isSet[DATE]
weekMonthSet
trueの場合useDate
、暗黙的に、日付情報を使用して時間の値を生成します。useDate
がfalseの場合、情報を使用しDAY_OF_WEEK
て予想時間を計算できるため、結果として差が生じます。
getTimeInMillis()
最後に、これにより、呼び出す前に呼び出すgetTime()
と予期しない動作が修正されるのはなぜかという疑問が生じます。結局のところ、両方のオブジェクトを呼び出した結果、フィールドが再計算されます。これは、(おそらく本物の)理由が何であれ、時間が計算された後set(field, value)
に発生します。したがって、時間を1秒に1回計算するように強制すると、基本的に2つのオブジェクトの状態が整列します。その後、への呼び出しはすべて、両方のオブジェクトで一貫して機能するはずです。Calendar
get*()
理想的には、2番目のケースで使用したコンストラクターは、一貫性の名の下にこの最初の計算ステップを実行する必要があります(ただし、パフォーマンス上の理由から、これは好ましくありません)が、そうではなく、これが得られます。
つまり、他の人が述べたように、JodaTimeはあなたの友達であり、明らかにこれらのクラスはそれほどではありません。:)