MonthDay 是 Java 8 引入的表示“月-日”组合的不可变类,专用于生日、节日等每年重复场景,语义更准确、避免闰年等问题;支持 of()、parse()、getMonthDay() 创建,equals() 判断匹配,atYear() 结合 LocalDate 计算天数。

MonthDay 是 Java 8 引入的 java.time 包中专门表示“月-日”组合的不可变类,不带年份,天然适合处理生日、节日等每年重复的日期场景。
为什么用 MonthDay 而不是 LocalDate?
因为生日(如 1995-05-20)和节日(如 2024-10-01 国庆节)本质上是“每年固定月日”,与具体年份无关。用 LocalDate 容易误带年份逻辑(比如闰年 2 月 29 日在非闰年会出错),而 MonthDay 明确剥离年份,语义更准确、操作更安全。
创建和解析 MonthDay
支持多种常见方式初始化:
- 直接通过静态工厂方法:
MonthDay.of(5, 20)表示 5 月 20 日 - 从字符串解析(ISO 格式):
MonthDay.parse("--05-20")(注意双连字符前缀) - 从已有日期提取:
LocalDate.now().getMonthDay()或LocalDate.of(1990, 3, 8).getMonthDay()
判断某天是否为指定生日/节日
把用户输入的 LocalDate 转成 MonthDay,再用 equals() 比较即可,无需手动取月、日字段:
立即学习“Java免费学习笔记(深入)”;
MonthDay birthday = MonthDay.of(5, 20); LocalDate today = LocalDate.now(); boolean isBirthday = birthday.equals(today.getMonthDay());
✅ 支持闰年 2 月 29 日:若某人出生在 2000-02-29,LocalDate.of(2023, 2, 29) 会抛异常,但 MonthDay.of(2, 29) 合法,且 LocalDate.of(2024, 2, 29).getMonthDay().equals(MonthDay.of(2, 29)) 返回 true。
计算距离下一个生日还有几天
需结合当前年份推算“今年的生日”和“明年的生日”,再选最近的一个:
- 用
MonthDay.atYear(year)得到当年对应日期(如MonthDay.of(12, 25).atYear(2024)→2024-12-25) - 先尝试生成今年生日日期;如果已过,就用明年
- 再用
ChronoUnit.DAYS.between(today, nextBirthday)计算天数
小技巧:可封装成工具方法,自动处理 2 月 29 日在平年时按 2 月 28 日或 3 月 1 日处理(根据业务需要)。
不复杂但容易忽略:MonthDay 本身不提供“加减月日”运算(它没年份),所有时间计算必须升维到 LocalDate 或 YearMonth 等带年份的类型来完成。


















