Java 实例 – 获取年份、月份等(一文讲透)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
在 Java 开发中,日期和时间的处理是一个高频需求,无论是记录用户注册时间、计算订单有效期,还是分析业务数据的时间趋势,都离不开对年份、月份等时间信息的获取与操作。对于编程初学者而言,Java 的时间处理 API 可能显得复杂;而对中级开发者来说,如何高效、安全地操作时间对象是持续优化的方向。本文将以 “Java 实例 – 获取年份、月份等” 为主题,通过对比旧版与新版 API 的差异、提供具体代码示例和常见问题解决方案,帮助读者系统掌握这一核心知识点。
一、Java 时间处理的两大阵营:旧 API 与新 API
Java 的时间处理 API 经历了两次重大迭代:
- 旧 API(Date/Calendar):诞生于 JDK 1.0,设计上存在线程不安全、方法命名混乱等问题,例如
Calendar.MONTH
从 0 开始计数(0 表示一月)。 - 新 API(java.time 包):随 JDK 8 引入,基于 ISO 8601 标准设计,提供不可变对象和清晰的命名规则,例如
LocalDate
的getYear()
直接返回年份。
形象比喻:旧 API 像一台老式机械钟表,需要手动调整齿轮才能读取时间;而新 API 则像智能手表,通过触摸屏即可直观获取年、月、日等信息。
二、核心知识点详解:如何获取年份、月份等信息
1. 使用新 API(推荐)
LocalDate 类 是处理日期(不含时间)的首选工具。以下代码演示如何获取当前年份和月份:
import java.time.LocalDate;
import java.time.Month;
public class DateExample {
public static void main(String[] args) {
LocalDate currentDate = LocalDate.now();
int year = currentDate.getYear(); // 获取年份
Month month = currentDate.getMonth(); // 获取月份枚举值
int monthValue = currentDate.getMonthValue(); // 获取月份数值(1-12)
System.out.println("当前年份:" + year);
System.out.println("当前月份(枚举):" + month);
System.out.println("当前月份数值:" + monthValue);
}
}
输出示例:
当前年份:2023
当前月份(枚举):JULY
当前月份数值:7
2. 使用旧 API(兼容场景)
尽管新 API 更推荐,但在兼容旧代码时仍需了解旧 API 的用法:
import java.util.Calendar;
import java.util.Date;
public class LegacyDateExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
Date currentDate = calendar.getTime();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 注意:月份从 0 开始,需加 1
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("当前日期:" + currentDate);
System.out.println("年份:" + year);
System.out.println("月份:" + month);
System.out.println("日:" + dayOfMonth);
}
}
关键差异对比:
| 特性 | 新 API(java.time) | 旧 API(Date/Calendar) |
|---------------------|-----------------------------|-----------------------------|
| 线程安全 | 是(不可变对象) | 否(可变对象) |
| 月份计数 | 1-12(getMonthValue()
) | 0-11(需手动加 1) |
| 代码可读性 | 高(方法名直观) | 低(依赖常量如 Calendar.YEAR
) |
三、进阶场景:时区与格式化
1. 处理时区差异
当需要获取特定时区的时间时,新 API 提供了 ZoneId
类:
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TimeZoneExample {
public static void main(String[] args) {
ZoneId zone = ZoneId.of("Asia/Shanghai");
ZonedDateTime shanghaiTime = ZonedDateTime.now(zone);
System.out.println("上海当前时间:" + shanghaiTime);
}
}
2. 自定义日期格式
使用 DateTimeFormatter
可以将日期对象格式化为字符串:
import java.time.format.DateTimeFormatter;
public class FormatExample {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2023, 7, 15);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String formattedDate = date.format(formatter);
System.out.println("格式化后的日期:" + formattedDate); // 输出:2023年07月15日
}
}
四、常见问题与解决方案
1. 月份从 0 开始的问题(旧 API)
在旧 API 中,Calendar.MONTH
的值范围是 0(一月)到 11(十二月),因此需通过 +1
转换为实际月份:
int actualMonth = calendar.get(Calendar.MONTH) + 1;
2. 跨时区计算日期差异
若需计算两个不同时区的日期差异,可使用 ZonedDateTime
和 ChronoUnit
:
import java.time.temporal.ChronoUnit;
public class TimeDifferenceExample {
public static void main(String[] args) {
ZonedDateTime newYork = ZonedDateTime.now(ZoneId.of("America/New_York"));
ZonedDateTime tokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
long hoursDifference = ChronoUnit.HOURS.between(newYork, tokyo);
System.out.println("纽约与东京时差:" + hoursDifference + " 小时");
}
}
3. 处理日期边界条件(如闰年)
新 API 内置了闰年判断功能:
LocalDate date = LocalDate.of(2024, 2, 29);
boolean isLeapYear = date.isLeapYear(); // 返回 true
五、实战案例:计算用户年龄
需求:根据用户出生日期,计算当前年龄。
实现步骤:
- 使用
LocalDate.now()
获取当前日期; - 通过
Period.between()
计算两个日期之间的年份差。
import java.time.LocalDate;
import java.time.Period;
public class AgeCalculator {
public static void main(String[] args) {
LocalDate birthDate = LocalDate.of(1990, 5, 15);
LocalDate currentDate = LocalDate.now();
Period age = Period.between(birthDate, currentDate);
System.out.println("用户年龄:" + age.getYears() + " 岁");
}
}
六、总结与建议
通过本文的讲解,读者可以掌握以下核心能力:
- 区分新旧 API 的优劣:优先使用
java.time
包,避免旧 API 的线程安全问题; - 灵活获取时间信息:通过
LocalDate
、LocalTime
和LocalDateTime
精准操作日期、时间及组合数据; - 处理复杂场景:时区转换、日期格式化、年龄计算等均可以通过新 API 的简洁方法实现。
推荐阅读:
- 若需深入学习时间 API,可查阅官方文档或《Java 8实战》相关章节;
- 对旧代码改造时,可使用
java.time包
的Instant
类与Date
进行互操作。
通过持续练习和代码实践,开发者可以快速提升对时间处理逻辑的理解,为构建高质量的 Java 应用打下坚实基础。