「年末取得」は“その年の最後の日を意味でつかまえる”こと
業務システムでは、「今年の年末」「会計年度の最終日」「前年の年末」みたいな話がよく出てきます。
ここでやってはいけないのは、「12 月 31 日で固定」と決め打ちしたり、自前で月の長さを計算したりすることです。
Java には、「その年の最後の日」を“名前付き”で安全に取り出すための API が用意されています。
それを素直に使うと、年次処理・年間集計・年度管理のコードが一気に読みやすくなります。
LocalDate から年末を取得する基本パターン
withMonth(12).withDayOfMonth(31) という素朴な書き方
まずは一番ストレートな書き方から。
import java.time.LocalDate;
public class YearEndBasic {
public static void main(String[] args) {
LocalDate anyDay = LocalDate.of(2025, 3, 26);
LocalDate yearEnd = anyDay.withMonth(12)
.withDayOfMonth(31);
System.out.println("任意の日付 : " + anyDay); // 2025-03-26
System.out.println("その年の年末: " + yearEnd); // 2025-12-31
}
}
Javaここで押さえておきたいのは、withXxx の性質です。
withMonth(12) は「同じ年・同じ日だが月だけ 12 月」、
さらに withDayOfMonth(31) で「その年の 12 月 31 日」になります。
元の anyDay は変わりません(不変オブジェクト)。
ただし、この書き方は「12 月 31 日が年末」という前提に乗っています。
暦年ベースなら問題ありませんが、会計年度が「4 月〜翌年 3 月」のようなケースでは、
別ロジックが必要になります(後で触れます)。
TemporalAdjusters を使った「年末」の書き方
lastDayOfYear() を使うと“意図が名前になる”
TemporalAdjusters には、「年初」「年末」などを
“意味のある名前”で表現するためのメソッドが用意されています。
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class YearEndAdjuster {
public static void main(String[] args) {
LocalDate anyDay = LocalDate.of(2025, 3, 26);
LocalDate yearEnd =
anyDay.with(TemporalAdjusters.lastDayOfYear());
System.out.println("任意の日付 : " + anyDay); // 2025-03-26
System.out.println("その年の年末: " + yearEnd); // 2025-12-31
}
}
Javawith(TemporalAdjusters.lastDayOfYear()) と書いてあるだけで、
「このコードは“年末を取っている”んだな」と一瞬で分かります。
withMonth(12).withDayOfMonth(31) よりも、
「意図がコードにそのまま出ている」という意味で、実務ではこちらを強くおすすめします。
「今年の年末」を取得する
LocalDate.now() と lastDayOfYear の組み合わせ
「今日が属する年の年末」を取りたい場合です。
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class ThisYearEnd {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate yearEnd =
today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("今日 : " + today);
System.out.println("今年の年末: " + yearEnd);
}
}
Java業務的には、
「今年の売上集計の最終日」「今年のログ抽出の終端」「今年のバッチ対象期間の終わり」などで、
この「今年の年末」が終点としてよく使われます。
「任意の年の年末」を求める
いったん年初を作ってから lastDayOfYear
「2025 年の年末」のように、年が決まっている場合です。
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class SpecificYearEnd {
public static void main(String[] args) {
LocalDate yearStart = LocalDate.of(2025, 1, 1);
LocalDate yearEnd =
yearStart.with(TemporalAdjusters.lastDayOfYear());
System.out.println("2025年の年初: " + yearStart); // 2025-01-01
System.out.println("2025年の年末: " + yearEnd); // 2025-12-31
}
}
Javaポイントは、
「年初は LocalDate.of(年, 1, 1) で素直に作り、年末は lastDayOfYear で求める」
というパターンを覚えておくことです。
「年初+年末」のセットで考えると、年間処理の期間計算がとても書きやすくなります。
LocalDateTime / ZonedDateTime での年末取得
LocalDateTime の年末(時刻をどこに合わせるかが重要)
LocalDateTime でも lastDayOfYear が使えます。
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
public class LocalDateTimeYearEnd {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 15, 30);
LocalDateTime yearEndSameTime =
dt.with(TemporalAdjusters.lastDayOfYear());
LocalDateTime yearEndAt235959 =
dt.with(TemporalAdjusters.lastDayOfYear())
.withHour(23).withMinute(59).withSecond(59).withNano(0);
System.out.println("元日時 : " + dt); // 2025-03-26T15:30
System.out.println("年末 同じ時刻 : " + yearEndSameTime); // 2025-12-31T15:30
System.out.println("年末 23:59:59まで : " + yearEndAt235959); // 2025-12-31T23:59:59
}
}
Java業務では、
「今年の 1 月 1 日 0:00 から、今年の 12 月 31 日 23:59:59 まで」
といった“年間の対象期間”を扱うことが多いので、
「日付だけでなく、時刻をどこに合わせるか」をきちんと決めることが大事です。
ZonedDateTime の年末(タイムゾーン付き)
タイムゾーン付きの ZonedDateTime でも同様です。
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAdjusters;
public class ZonedDateTimeYearEnd {
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.of(
2025, 3, 26,
15, 30, 0, 0,
ZoneId.of("Asia/Tokyo")
);
ZonedDateTime yearEnd =
zdt.with(TemporalAdjusters.lastDayOfYear())
.withHour(23).withMinute(59).withSecond(59).withNano(0);
System.out.println("元日時 : " + zdt);
System.out.println("年末 23:59:59: " + yearEnd);
}
}
Java「日本時間の年末」「UTC の年末」を区別したい場合や、
海外システムと連携する場合は、ZonedDateTime で年末を扱う方が安全です。
会計年度など「年末=12/31 ではない」ケース
例えば「4 月〜翌年 3 月」が年度の場合
暦年ではなく「会計年度」を扱う場合、
「年度の開始日」「年度の終了日」を自分で定義する必要があります。
例えば「2024 年度は 2024-04-01 〜 2025-03-31」と決まっているなら、
年度末はこう表現できます。
import java.time.LocalDate;
public class FiscalYearEndExample {
public static void main(String[] args) {
int fiscalYear = 2024; // 2024年度
LocalDate fiscalYearEnd = LocalDate.of(fiscalYear + 1, 3, 31);
System.out.println("2024年度の年度末: " + fiscalYearEnd); // 2025-03-31
}
}
Javaここで大事なのは、
「lastDayOfYear は“暦年”の年末であって、“会計年度の年末”ではない」
ということです。
会計年度を扱うときは、
「年度の定義」を一か所にまとめたユーティリティを作り、
そこに「年度初日」「年度末日」を計算させるのが実務的です。
実務での「年初+年末」セット利用
今年の対象期間(年初〜年末)を求める
「今年のデータだけを集計したい」という典型パターンです。
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
public class YearlyRangeExample {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDateTime from = today.with(TemporalAdjusters.firstDayOfYear())
.atStartOfDay();
LocalDateTime to = today.with(TemporalAdjusters.lastDayOfYear())
.atTime(23, 59, 59);
System.out.println("対象開始: " + from);
System.out.println("対象終了: " + to);
}
}
Javaここでのポイントは、
「年初取得」と「年末取得」をセットで使うと、“今年の範囲”をきれいに表現できる
ということです。
まとめ:年末取得で身につけてほしい感覚
年末取得は、「その年の最後の日」を安全かつ意図が伝わる形で取り出すことです。
LocalDate なら with(TemporalAdjusters.lastDayOfYear()) を使う。
「今年の年末」なら LocalDate.now().with(lastDayOfYear())。
LocalDateTime / ZonedDateTime では、日付に加えて「時刻をどこに合わせるか」を決める。
暦年ではなく会計年度を扱う場合は、「年度の定義」を自前でユーティリティ化する。
あなたのコードのどこかに、
「12 月 31 日をベタ書きして“年末扱い”している」ような箇所があれば、
そこを一度 lastDayOfYear() や年度ユーティリティに置き換えられないか眺めてみてください。
その小さな置き換えが、
“時間とカレンダーに強いエンジニア”への、また一歩になります。
