1. 概述
Java 8 的发布彻底改变了日期处理的方式。新的 java.time
包下的 Date & Time API 相比老旧的 java.util.Date
和 Calendar
,使用起来更加直观、安全且不易出错。本文聚焦于如何创建带有具体值的 LocalDate
,这是日常开发中非常常见的需求。
LocalDate
是 java.time
包中的核心类之一,它是一个✅ 不可变、线程安全的对象,仅用于表示日期(年月日),❌ 不包含时间部分,也不带时区信息。
接下来,我们将系统性地介绍几种创建 LocalDate
实例的方法。
2. 使用 of() 方法创建自定义 LocalDate
这是最直接、最常用的方式。我们可以通过 LocalDate.of()
工厂方法传入年、月、日来创建一个指定日期。
以创建 2020 年 1 月 8 日为例:
LocalDate date = LocalDate.of(2020, 1, 8);
⚠️ 注意:月份参数使用数字时,1 表示一月,12 表示十二月,不是从 0 开始的,这一点和 Calendar
类完全不同,避免了常见的“月份踩坑”。
更推荐的做法是使用 Month
枚举,代码可读性更强,也更安全:
LocalDate date = LocalDate.of(2020, Month.JANUARY, 8);
此外,LocalDate
还提供了基于“纪元日”(Epoch Day)的创建方式。纪元日是从 1970-01-01(UTC)开始计算的天数:
LocalDate date = LocalDate.ofEpochDay(18269); // 对应 2020-01-08
最后,如果知道某年中的第几天,也可以使用 ofYearDay()
方法:
LocalDate date = LocalDate.ofYearDay(2020, 8); // 2020 年的第 8 天,即 1 月 8 日
✅ 小结:
of()
是最推荐的创建方式,清晰明了;Month
枚举优于魔法数字;ofEpochDay
和ofYearDay
在特定场景下很有用。
3. 通过解析字符串创建 LocalDate
当日期以字符串形式存在(如从配置文件、网络接口或用户输入中获取)时,我们需要将其解析为 LocalDate
。
LocalDate.parse()
方法默认支持 ISO-8601 格式的字符串(yyyy-MM-dd
):
LocalDate date = LocalDate.parse("2020-01-08");
如果字符串格式不同,比如 "8-Jan-2020"
,则需要配合 DateTimeFormatter
指定解析模式:
LocalDate date = LocalDate.parse("8-Jan-2020", DateTimeFormatter.ofPattern("d-MMM-yyyy"));
这里 "d-MMM-yyyy"
是自定义的格式模式:
d
:表示日(1-31)MMM
:表示缩写的月份名称(如 Jan, Feb)yyyy
:表示四位年份
⚠️ 踩坑提醒:解析时务必确保字符串格式与
DateTimeFormatter
定义的模式完全匹配,否则会抛出DateTimeParseException
。建议在生产环境中对输入做校验。
4. 总结
本文系统梳理了 Java 8 Date & Time API 中创建 LocalDate
的四种主要方式:
- ✅
LocalDate.of(year, month, day)
:最常用,推荐使用Month
枚举 - ✅
LocalDate.ofEpochDay(epochDay)
:基于纪元日创建 - ✅
LocalDate.ofYearDay(year, dayOfYear)
:基于年内的第几天创建 - ✅
LocalDate.parse(text, formatter)
:解析字符串,灵活支持各种格式
这些方法简单粗暴且类型安全,彻底告别了 SimpleDateFormat
的线程安全问题和 Calendar
的晦涩 API。
示例代码已托管至 GitHub: https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-8-datetime-2