Java Date 类深度解析
Java Date 类深度解析
1. Date 类核心知识
(1) 基本概念
-
作用:表示特定的瞬间,精确到毫秒
-
存储本质:内部维护一个long型变量,存储自1970-01-01 00:00:00 GMT(Unix纪元)以来的毫秒数
(2) 关键构造方法
java
// 1. 无参构造:当前系统时间
Date now = new Date(); // 2. 指定毫秒数构造
Date date = new Date(1625097600000L); // 2021-06-30 00:00:00// 3. 已废弃构造方法(不推荐)
@Deprecated
public Date(int year, int month, int day) // 年份要+1900,月份0-11
(3) 常用方法
方法 | 作用 | 示例 |
---|---|---|
getTime() | 获取毫秒时间戳 | long ts = date.getTime() |
setTime(long) | 设置时间 | date.setTime(0L) |
after(Date) | 时间比较 | date1.after(date2) |
before(Date) | 时间比较 | date1.before(date2) |
2. 新旧API对比
(1) 遗留问题
-
缺陷1:月份从0开始(0=一月)
-
缺陷2:年份需要+1900
-
缺陷3:非线程安全(SimpleDateFormat同理)
(2) 替代方案(Java 8+)
java
// 使用Instant替代Date
Instant instant = Instant.now();// 本地日期时间
LocalDateTime ldt = LocalDateTime.now();// 时区转换
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
3. 格式化与解析
(1) 传统方式(SimpleDateFormat)
java
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化
String str = sdf.format(new Date()); // "2023-05-20 14:30:00"// 解析(注意异常处理)
Date date = sdf.parse("2023-05-20 14:30:00");
(2) 线程安全方案
java
// 方案1:ThreadLocal包装
private static final ThreadLocal<DateFormat> SAFE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));// 方案2:DateTimeFormatter(推荐)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate ld = LocalDate.parse("2023-05-20", formatter);
4. 典型应用场景
(1) 耗时计算
java
Date start = new Date();
// 执行操作...
Date end = new Date();
long cost = end.getTime() - start.getTime(); // 毫秒耗时
(2) 日期比较
java
// 方法1:compareTo
int result = date1.compareTo(date2);// 方法2:时间戳比较
boolean isLater = date1.getTime() > date2.getTime();
5. 常见问题与陷阱
(1) 时区问题
java
// 错误示范:忽略时区
Date date = new Date(); // 默认系统时区// 正确做法:明确时区
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
(2) 月份陷阱
java
// 错误:月份从0开始
Date date = new Date(2023-1900, 5, 20); // 实际是6月// 正确:使用Calendar或新API
Calendar cal = Calendar.getInstance();
cal.set(2023, Calendar.MAY, 20);
6. 最佳实践建议
-
新项目优先使用java.time包(LocalDateTime等)
-
必须使用Date时:
-
用
System.currentTimeMillis()
替代new Date()
-
日期格式化工具有线程安全措施
-
-
时区敏感场景:
-
存储UTC时间
-
显示时转换为本地时区
-
7. 面试高频问题
-
Q:Date和Calendar有什么区别?
A:Date侧重时间点,Calendar提供日期计算功能 -
Q:如何解决SimpleDateFormat线程安全问题?
A:ThreadLocal隔离或使用DateTimeFormatter -
Q:为什么Date的大部分方法被废弃?
A:设计缺陷(时区处理差、API不直观)
记忆口诀:
"Date存毫秒,纪元是基准"
"月份从0始,年份1900加"
"新项目用java.time,线程安全记心间"