次のコードが2009年8月22日(土曜日)に実行されたとします。
_ Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
_
c.get(Calendar.DAY_OF_MONTH)
は23を返します。14が返される(次の日曜日ではなく、最終日曜日)という条件に興味があります。
_DAY_OF_MONTH/YEAR
_が設定されている場合、カレンダーが_DAY_OF_WEEK
_をロールする方向に関連付けられたルールはありますか?もしそうなら、彼らは何ですか?
常に同じにする必要がありますWEEK_OF_MONTH
( http://Java.Sun.com/j2se/1.4.2/docs/api/Java/util/Calendar.html#WEEK_OF_MONTH )。ドキュメントから:
WEEK_OF_MONTHまたはWEEK_OF_YEARフィールドを設定または取得する場合、カレンダーは月または年の最初の週を基準点として決定する必要があります。月または年の最初の週は、getFirstDayOfWeek()で始まり、その月または年の少なくともgetMinimalDaysInFirstWeek()日を含む最も早い7日間として定義されます。週番号は...、-1、0は最初の週の前。週は2、3、...と続きます。 get()によって返される正規化された番号付けは異なる場合があることに注意してください。たとえば、特定のCalendarサブクラスは、年の第1週の前の週を前年の第n週として指定する場合があります。
次の数式は、[0; 6]の範囲で、週の「現在」の日を返します
_(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek
_
または、範囲[1; 7]が必要な場合は1を追加します
_(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek + 1
_
d
はCalendar.get(Calendar.DAY_OF_WEEK)
が返すものです
週の最初の日を取得するには、現在の日付から数式の結果を引きます。次のコードはそれを行います:
_final int currentDayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 7 - cal.getFirstDayOfWeek()) % 7;
cal.add(Calendar.DAY_OF_YEAR, -currentDayOfWeek);
_
それは実際に依存します。次のJavaコードを検討してください。実際には非常に単純であり、2011-09-18の前の月曜日、つまり2011-09-12を出力すると予想されます。
Calendar calendar = Calendar.getInstance(Locale.GERMANY);
System.out.printf("First day of week: %d%n%n", calendar.getFirstDayOfWeek());
calendar.set(2011, Calendar.SEPTEMBER, 18);
System.out.printf("Starting day: %tF%n", calendar);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.printf("Last monday: %tF%n%n", calendar);
calendar.set(2011, Calendar.SEPTEMBER, 18);
System.out.printf("Starting day: %tF (week %d)%n",
calendar, calendar.get(Calendar.WEEK_OF_YEAR));
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.printf("Last monday: %tF (week %d)%n", calendar,
calendar.get(Calendar.WEEK_OF_YEAR));
しかし、実際には結果は少し異なります。
First day of week: 2
Starting day: 2011-09-18
Last monday: 2011-09-19
Starting day: 2011-09-18 (week 37)
Last monday: 2011-09-12 (week 37)
言い換えれば、結果は、私の週に興味があるかもしれないことを私のカレンダーが知っているかどうかによって異なります。 WEEK_OF_YEAR
!をクエリすると、結果は実際に変わります。
現代のアプローチは、面倒な古いレガシーの日時クラスに取って代わるJava.timeクラスを使用しています。
Java.timeクラスは、操作がはるかに簡単です。特に、彼らは質問で提起された曖昧さを取り除きます。 earlier日曜日またはlater日曜日を明示的に要求できます。
LocalDate
クラスは、時刻とタイムゾーンなしの日付のみの値を表します。
Month
enumは、1か月に1つずつ、12個の定義済みオブジェクトを提供します。これらの列挙型オブジェクトを使用する方が安全ですが、代わりに月の単純な数値を使用できます。従来のクラスとは異なり、これらの月には適切な番号が付けられており、1月から12月は1〜12です。
LocalDate localDate = LocalDate.of( 2009 , Month.AUGUST, 22 );
TemporalAdjuster
インターフェイスは、日時値の操作を提供します。 TemporalAdjusters
クラス(複数形s
に注意)は、いくつかの便利な実装を提供します。
previous
&next
アジャスターは日付自体を考慮から除外します。 previousOrSame
&nextOrSame
メソッドは、目的の曜日である場合、問題の日付を返します。
DayOfWeek
enumは、曜日ごとに1つずつ、7つの定義済みオブジェクトを提供します。
LocalDate previousSunday = localDate.with( TemporalAdjusters.previous ( DayOfWeek.SUNDAY ));
LocalDate previousOrSameSunday = localDate.with( TemporalAdjusters.previousOrSame ( DayOfWeek.SUNDAY ));
LocalDate nextSunday = localDate.with( TemporalAdjusters.next ( DayOfWeek.SUNDAY ));
LocalDate nextOrSameSunday = localDate.with( TemporalAdjusters.nextOrSame ( DayOfWeek.SUNDAY ));
コンソールにダンプします。
System.out.println ("localDate: " + localDate + " ( " + localDate.getDayOfWeek ().getDisplayName ( TextStyle.FULL, Locale.US ) + " )");
System.out.println ("previousSunday: " + previousSunday );
System.out.println ("nextSunday: " + nextSunday );
localDate:2009-08-22(土曜日)
前日曜日:2009-08-16
来週日曜日:2009-08-23
Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは、面倒な古い レガシー のような日時クラスに取って代わります- Java.util.Date
、 Calendar
、& SimpleDateFormat
。
Joda-Time プロジェクトは現在 maintenance mode であり、 Java.time クラスへの移行を推奨しています。
詳細については、 Oracleチュートリアル を参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様は JSR 31 です。
Java.timeクラスはどこで入手できますか?
ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性があることを証明する場です。 Interval
、 YearWeek
、 YearQuarter
のようないくつかの便利なクラスがここにあります。 、および more 。
Javadoc から:
カレンダフィールドの値に矛盾がある場合、Calendarは、最近設定されたカレンダフィールドを優先します。以下は、カレンダーフィールドのデフォルトの組み合わせです。最後に設定された単一のフィールドによって決定される最新の組み合わせが使用されます。
日付フィールドの場合:
YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
これは、曜日を設定している場合、実際の日付と時刻を生成するために月の週または年の週と組み合わせられることを意味すると解釈します。
週の最初の日も確認する必要があります。いつも日曜日だと思っていましたが、これはローカルの設定に依存し、私の場合は月曜日が週の最初の日です。日曜日を週の最初の日として設定すると、問題が解決しました。
週の最初の日に依存:
/**
* Gets what the first day of the week is; e.g., <code>SUNDAY</code> in the U.S.,
* <code>MONDAY</code> in France.
*
* @return the first day of the week.
* @see #setFirstDayOfWeek(int)
* @see #getMinimalDaysInFirstWeek()
*/
public int getFirstDayOfWeek()
{
return firstDayOfWeek;
}