1. 概述
✅ 本文将介绍在 Java 中如何从一个日期对象中提取年(Year)、月(Month)和日(Day)的整数值。
我们会覆盖三种主流方式:
- 使用传统的
java.util.Date
和Calendar
- 处理
java.sql.Timestamp
- 使用 Java 8 引入的现代日期时间 API(
java.time
)
⚠️ 为什么要用新 API?因为老的 Date
和 Calendar
设计存在诸多问题:线程不安全、API 设计混乱、月份从 0 开始等。Java 8 的 java.time
包解决了这些问题,代码更清晰、更安全。
如果你还没用过 Java 8 的时间类,建议先看这篇入门文章:Java 8 日期时间 API 简介。
本文所有示例代码已上传至 GitHub:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-date-operations-1
2. 使用 LocalDate(推荐方式)
✅ LocalDate
是 Java 8 java.time
包中最常用的日期类之一,仅表示日期(不含时间)。
它提供了直观的方法直接获取年、月、日,无需中间转换,简单粗暴又安全。
假设我们有一个 LocalDate
实例:
LocalDate localDate = LocalDate.of(2023, 10, 25);
2.1. 获取年份
直接调用 getYear()
:
int year = localDate.getYear(); // 返回 2023
2.2. 获取月份
使用 getMonthValue()
获取月份数值:
int month = localDate.getMonthValue(); // 返回 10(10月)
📌 注意:LocalDate
的月份从 1 开始计数,1 表示一月,12 表示十二月。这和人类直觉一致,避免踩坑。
❌ 对比老的
Calendar
,它的月份是从 0 开始的,一月是 0,非常容易出错。
2.3. 获取日
使用 getDayOfMonth()
获取当月的第几天:
int day = localDate.getDayOfMonth(); // 返回 25
3. 使用 java.util.Date(旧方式,不推荐)
⚠️ Date
类本身没有提供直接获取年月日的方法,必须借助 Calendar
中转。
步骤:
- 创建
Calendar
实例 - 将
Date
设置进去 - 调用
get()
方法提取字段
示例代码:
Date date = new Date(); // 当前时间
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
3.1. 获取年份
int year = calendar.get(Calendar.YEAR); // 返回 2023
3.2. 获取月份
int month = calendar.get(Calendar.MONTH); // 返回 9(注意!10月返回9)
📌 大坑警告:Calendar.MONTH
是从 0 开始的!
- 一月 → 0
- 十月 → 9
这个设计反人类,极易导致 bug,务必小心。
3.3. 获取日
int day = calendar.get(Calendar.DAY_OF_MONTH); // 返回 25
✅ 建议:除非维护老系统,否则不要用这种方式。
4. 使用 java.sql.Timestamp
Timestamp
通常用于数据库操作,表示带纳秒精度的时间戳。
但它本身也不支持直接提取年月日,仍需通过 Calendar
中转。
步骤:
- 创建
Calendar
实例 - 将
Timestamp
设置进去 - 使用
get()
提取字段
示例代码:
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Calendar calendar = Calendar.getInstance();
calendar.setTime(timestamp);
之后提取方式与 Date
完全一致:
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH); // 注意:仍是 0 起始
int day = calendar.get(Calendar.DAY_OF_MONTH);
⚠️ 虽然 Timestamp
继承自 Date
,但其 getYear()
、getMonth()
等方法已被标记为 @Deprecated
,不要使用。
5. 总结
方式 | 是否推荐 | 关键点 |
---|---|---|
✅ LocalDate |
强烈推荐 | 月份从 1 开始,API 简洁,线程安全 |
❌ Date + Calendar |
不推荐 | 月份从 0 开始,易出错,API 冗长 |
⚠️ Timestamp + Calendar |
仅限数据库场景 | 同上,注意弃用方法 |
📌 最佳实践建议:
- 新项目一律使用
java.time
包(如LocalDate
) - 老项目迁移时,优先替换
Date/Calendar
相关逻辑 - 遇到
Timestamp
,可先转为Instant
或LocalDateTime
,再提取字段,避免依赖Calendar
完整代码示例见 GitHub:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-date-operations-1