小ネタ。「今年の12月に解約したい。日割りが必要ない日付を教えてほしい」といった、解約する「年月」までは把握しているが、解約する「年月日」までは分からないといったケースに対応するロジックをJavaで求めます。
環境
- Java
- 17
対応
暦上の1ヵ月の定義については、こちらの記事を見てください。
雑に表現すると次のどちらかです。
- 開始日の"日" -1日
- 月末
月末はYearMonth
型を使用すると非常に楽ですので、まずは「解約月」をYearMonth
型に変換します。
YearMonth#isValidDay
にて、指定日付が存在するかをチェックできます。YearMonth#atDay
にて、指定の日付のLocalDate
型に変換できます。それぞれのパラメータに「開始日の日-1日」を渡します。もし指定日付が存在すれば、その日付が「解約日」となります。存在しなければ、「解約日」は月末です。
public LocalDate from年月to日割りなし日付(LocalDate startDate, LocalDate endMonth) { YearMonth yearMonth = YearMonth.from(endMonth); if (yearMonth.isValidDay(localDate.getDayOfMonth() - 1)) { return yearMonth.atDay(localDate.getDayOfMonth() - 1); } else { return yearMonth.atEndOfMonth(); } }
なお、存在しない日付とは次のケースです。
- 開始日が1日
- パラメータが0日になるため
- 存在しない日付
- 2月30日 等々 閏年も含む
ソースコード
テストケースはこの記事参照してください。
- https://github.com/hirotoKirimaru/cucumber-sample/blob/b833df714320bd21c90ade4dc0f81a95455966a2/kirimaru-core/src/main/java/kirimaru/biz/domain/RequestDate.java#L53
- https://github.com/hirotoKirimaru/cucumber-sample/blob/b833df714320bd21c90ade4dc0f81a95455966a2/kirimaru-core/src/test/java/kirimaru/biz/domain/RequestDateTests.java#L61
終わりに
テストケースさえ思いつけばシンプルです。
LocalDate
のまま処理するとチェックメソッドがないため、DateTimeException
が発生していたのですが、YearMonth#isValidDay
のおかげで安全に処理できました。
地味な内容ですが、検証することでYearMonth#isValidDay
の存在に気づけて良かったです。