次の月の最終日が送信予定の通知である場合の計算に問題があります。
ここに私のコードがあります:
RecurrenceFrequency recurrenceFrequency = notification.getRecurrenceFrequency();
Calendar nextNotifTime = Calendar.getInstance();
これは私が信じる問題を引き起こす行です:
nextNotifTime.add(recurrenceFrequency.getRecurrencePeriod(),
recurrenceFrequency.getRecurrenceOffset());
カレンダーを使用して、通知の翌月の最終日を適切に設定するにはどうすればよいですか?
Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);
これは、現在の月の実際の最大値を返します。たとえば、現在はうるう年の2月なので、int
として29を返します。
Java 8に組み込まれたJava.time
ライブラリを使用すると、TemporalAdjuster
クラス(または TemporalAdjusters
ユーティリティクラス )を使用できます。
import Java.time.LocalDate;
import Java.time.temporal.TemporalAdjusters;
LocalDate now = LocalDate.now(); //2015-11-23
LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth()); //2015-11-30
時間情報を追加する必要がある場合は、次のような利用可能なLocalDateからLocalDateTimeへの変換を使用できます。
lastDay.atStartOfDay(); //2015-11-30T00:00
そして、Dateオブジェクトとして最終日を取得するには:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
Date lastDayOfMonth = cal.getTime();
カレンダーを来月の最初に設定してから日を引くことができます。
Calendar nextNotifTime = Calendar.getInstance();
nextNotifTime.add(Calendar.MONTH, 1);
nextNotifTime.set(Calendar.DATE, 1);
nextNotifTime.add(Calendar.DATE, -1);
このコードを実行すると、nextNotifTimeは現在の月の最終日に設定されます。今日が月の最後の日である場合、このコードの最終的な効果は、Calendarオブジェクトが変更されないことです。
以下は常に適切な結果を提供します:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, ANY_MONTH);
cal.set(Calendar.YEAR, ANY_YEAR);
cal.set(Calendar.DAY_OF_MONTH, 1);// This is necessary to get proper results
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
cal.getTime();
最新のJava.time
ライブラリを使用するのが最適なソリューションです。
LocalDate date = LocalDate.now();
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
または、次のこともできます。
LocalDate endOfMonth = date.withDayOfMonth(date.lengthOfMonth());
CalendarオブジェクトのgetActualMaximum(int field)
メソッドを見てください。
Calendarオブジェクトを、最後の日付を探している月に設定すると、getActualMaximum(Calendar.DAY_OF_MONTH)
が最終日を返します。
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = sdf.parse("11/02/2016");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
System.out.println("First Day Of Month : " + calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
System.out.println("Last Day of Month : " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
YearMonthも使用できます。
のような:
YearMonth.of(2019,7).atEndOfMonth()
YearMonth.of(2019,7).atDay(1)
https://docs.Oracle.com/javase/8/docs/api/Java/time/YearMonth.html#atEndOfMonth-- を参照してください
Java.util.Calendar
を使用したKotlin日付拡張機能の実装
fun Date.toEndOfMonth(): Date {
return Calendar.getInstance().apply {
time = this@toEndOfMonth
}.toEndOfMonth().time
}
fun Calendar.toEndOfMonth(): Calendar {
set(Calendar.DAY_OF_MONTH, getActualMaximum(Calendar.DAY_OF_MONTH))
return this
}
Date().toEndOfMonth()
のような各DateオブジェクトでtoEndOfMonth
関数を呼び出すことができます