讲师中心 微信公众号
AI工具推荐 视频效率加速

Java常用日期时间类库Date与Calendar

浅涛大大_1596

浅涛大大_1596

发布时间:2026-01-11 12:25:02

|

322人浏览过

|

来源于php中文网

原创

Date类不能直接用于日期计算,因其设计缺陷:月份从0开始、年份以1900为基点、方法非线程安全且已废弃;Calendar需clear再set字段以防状态残留;新项目应使用Java 8+的不可变、线程安全的java.time API。

java常用日期时间类库date与calendar

Java中Date类为什么不能直接用作日期计算

Date 类在 JDK 1.0 就已存在,但它的大部分方法(如 setYear()、getMonth()、getDate())从 JDK 1.1 起就被标记为 @Deprecated。这不是因为功能失效,而是设计缺陷:月份从 0 开始(0 表示一月),年份以 1900 为基点(123 表示 2023 年),且所有方法都不是线程安全的。

常见错误现象:

  • 调用 date.getMonth() 返回 0 却误以为是一月以外的月份
  • 用 new Date(2023, 1, 1) 构造对象,结果得到的是 2024 年 2 月 1 日(因年份+1900、月份+1)
  • 多线程环境下共享 Date 实例并调用 setTime(),导致时间值错乱

实际使用中,Date 仅建议作为「时间戳载体」——即只通过 getTime() 获取 long 值,或用构造函数 new Date(long) 初始化。所有业务逻辑中的日期操作,应避免直接调用其已废弃方法。

Calendar类做日期加减时必须先clear再set

Calendar 是 Date 的“补丁式替代”,但它内部状态复杂:字段未显式设置时可能沿用上一次实例的缓存值,尤其在复用同一 Calendar 实例时极易出错。

立即学习“Java免费学习笔记(深入)”;

典型错误写法:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2023);
cal.add(Calendar.DAY_OF_MONTH, 5); // 你以为是2023-xx-xx加5天?其实可能还是2024年的某天

原因:getInstance() 返回的 Calendar 包含完整当前时间(年月日时分秒毫秒),只调用 set(Calendar.YEAR, 2023) 并不会清空月、日等字段,后续 add() 会在原有基础上叠加。

正确做法:

  • 每次重用前必须调用 cal.clear()
  • 再按需 set() 年、月、日等字段(注意月份仍从 0 开始)
  • 执行 add() 或 roll() 前确保字段已明确初始化

示例:

Gradle 9.8.0
Gradle 9.8.0

Gradle 9.8.0 官方二进制分发包,适用于 Windows、macOS 与 Linux 的 Java、Kotlin 和 Android 项目构建。

下载
Calendar cal = Calendar.getInstance();
cal.clear(); // 关键!
cal.set(Calendar.YEAR, 2023);
cal.set(Calendar.MONTH, Calendar.JANUARY); // = 0
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.add(Calendar.DAY_OF_MONTH, 5); // 确保是2023-01-06

Calendar.getTime()返回的Date对象仍是可变的

很多人以为调用 calendar.getTime() 得到一个“快照”后,就可以放心修改原 Calendar。但这个 Date 对象内部只是包装了同一个 long time 值,它本身不隔离状态。

问题在于:Date 的 setTime()、setHours() 等方法依然可用,一旦被意外调用,会污染原始时间语义。

更隐蔽的风险:

  • 将 calendar.getTime() 传给外部方法,而该方法内部调用了 date.setTime(...)
  • 把返回的 Date 存入可变容器(如 ArrayList),之后又对容器中元素调用 setTime()

因此,如果必须返回时间表示,优先考虑:

  • 返回 calendar.getTimeInMillis() 的 long 值(不可变)
  • 或封装成 Instant(Java 8+):Instant.ofEpochMilli(calendar.getTimeInMillis())
  • 若必须返回 Date,至少做防御性拷贝:new Date(calendar.getTimeInMillis())

别再用Date和Calendar处理新项目的时间逻辑

Java 8 引入的 java.time 包(如 LocalDateTime、ZonedDateTime、Duration、Period)已彻底解决上述所有问题:不可变、线程安全、语义清晰、无魔法数字。

迁移成本其实很低:

  • new Date() → Instant.now()
  • calendar.get(Calendar.YEAR) → LocalDateTime.now().getYear()
  • calendar.add(Calendar.MONTH, 1) → localDate.plusMonths(1)

唯一需要警惕的是遗留接口:比如 JDBC 的 PreparedStatement.setDate() 还要求 java.sql.Date。这时应严格遵循转换规范:java.sql.Date.valueOf(localDate) 或 Timestamp.from(instant),而不是用 new java.sql.Date(date.getTime()) 这种绕过类型语义的写法。

老代码里还藏着 Date 和 Calendar 不代表必须容忍它们——只要涉及日期计算、格式化、时区转换,就该视为技术债立即重构。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

4423

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

931

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1169

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

6361

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

3183

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

6340

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

8641

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1170

2024.04.29

剧云故事大纲与分场规划教程
剧云故事大纲与分场规划教程

本专题讲解剧云梗概与多级大纲功能,覆盖全局、分集、分场结构生成,以及主线冲突、剧情节点和场次顺序调整。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn