monthday 是 java 8 引入的表示“月-日”组合的不可变类,用于处理生日等年度重复日期;支持 of()、from()、parse() 创建,需结合年份计算天数,不实现 comparable 且需注意 2 月 29 日异常。

MonthDay 是 Java 8 引入的 java.time 包中专门表示“月-日”组合的不可变类,不带年份,非常适合处理生日、纪念日、节日等每年重复的日期(如 5 月 20 日、12 月 25 日)。
创建和解析 MonthDay
常见方式有三种:
- 用静态工厂方法:
MonthDay.of(5, 20)→ 表示 5 月 20 日 - 从 LocalDate 解析:
MonthDay.from(LocalDate.of(1990, 3, 8))→ 提取月日部分 - 解析字符串:
MonthDay.parse("--07-15")(注意格式必须是--MM-dd,开头两个短横线不能省)
判断今天是否是某个 MonthDay
把当前日期转成 MonthDay,再用 equals() 比较即可:
例如判断今天是不是你的生日(假设生日是 10 月 12 日):
MonthDay birthday = MonthDay.of(10, 12);
MonthDay today = MonthDay.from(LocalDate.now());
if (today.equals(birthday)) {
System.out.println("生日快乐!");
}
计算距离下一个该节日还有几天
需要结合年份才能算天数。通用做法是:取今年的对应日期,如果已过就用明年:
- 构造今年的 LocalDate:
LocalDate thisYear = birthday.atYear(Year.now().getValue()) - 如果
thisYear.isBefore(LocalDate.now()),则改用birthday.atYear(Year.now().getValue() + 1) - 再用
ChronoUnit.DAYS.between(LocalDate.now(), targetDate)得到天数
注意事项和常见坑
-
不能直接比较大小:MonthDay 不实现 Comparable,也不支持
或 <code>>;如需排序或判断“是否在某月日前”,应先转为同一年的 LocalDate 再比 -
不处理闰年 2 月 29 日的特殊逻辑:MonthDay.of(2, 29) 合法,但用它生成 LocalDate 时(如
atYear(2023))会抛 DateTimeException —— 需手动兜底(比如平年用 2 月 28 日或 3 月 1 日) -
格式化输出要小心:
toString()返回--05-20,如需“5月20日”这类中文格式,建议用DateTimeFormatter.ofPattern("M月d日")配合 LocalDate(临时补一个年份)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











