在Java里Calendar类如何进行日期计算_Java时间操作方式说明
发布时间 - 2026-02-02 00:00:00 点击率:次Calendar.add()会自动进位/借位并传播溢出,而set()和roll()不会;必须调用getTime()获取结果;现代Java应优先使用java.time API。
Calendar.add() 是最常用也最容易出错的日期计算方式
直接修改 Calendar 实例的字段(如 set())不会触发自动进位或借位,而 add() 会——比如给 1 月 31 日加 1 个月,结果是 2 月 28/29 日(取决于闰年),不是 2 月 31 日报错。但很多人误以为它和 roll() 一样只影响当前字段。
-
add()会“溢出传播”:加天数可能影响月、年;加月可能影响年;加小时可能影响日 -
roll()不传播:对 1 月 31 日roll(Calendar.MONTH, 1),结果仍是 1 月 28/29/30/31 日(只在 1 月内滚动) - 必须调用
getTime()获取计算后的Date,否则字段变更未生效(Calendar是可变对象,但内部状态需显式提取)
Calendar cal = Calendar.getInstance(); cal.set(2025, Calendar.JANUARY, 31); // 注意:月份从 0 开始 cal.add(Calendar.MONTH, 1); // 得到 2025-02-28 Date result = cal.getTime(); // 必须调用!
为什么 new GregorianCalendar().add() 后 getTime() 还是旧时间?
常见错误是重复使用同一个 Calendar 实例却忘记重置或未正确初始化。更隐蔽的问题是时区和默认 Locale 导致的隐式行为差异——比如在某些 JVM 环境下,getInstance() 返回的 GregorianCalendar 可能启用 lenient 模式,允许非法日期临时存在,直到你调用 getTime() 才真正校正。
- 默认
lenient = true:设 2025-02-30 会被静默转为 2025-03-02,不报错但结果意外 - 设
cal.setLenient(false)后,非法日期设置会立即抛IllegalArgumentException - 构造后立刻
clear()再set(),避免残留字段干扰(尤其复用实例时)
Calendar 计算跨月/跨年时的时区陷阱
Calendar 的所有计算都基于其内部 TimeZone,但 add() 对小时、分钟的操作受 DST(夏令时)影响。例如在 CEST 时区(UTC+2),3 月最后一个周日凌晨 2:00 会跳到 3:00,此时对那个时刻加 1 小时,结果不是 3:00 而是 4:00(跳过了不存在的 3:00–4:00 区间)。
- 用
cal.getTimeZone().getOffset(cal.getTimeInMillis())查当前毫秒值对应的时区偏移 - 跨 DST 边界计算建议先转成 UTC 时间(用
SimpleDateFormat配合TimeZone.getTimeZone("UTC"))再操作 - 避免用
add(Calendar.HOUR, 24)代替:前者受 DST 影响,后者按日历日推进
add(Calendar.DAY_OF_MONTH, 1)
替代方案:Java 8+ 应该优先用 LocalDate / LocalDateTime
Calendar 是遗留 API,线程不安全、设计反直觉、时区处理隐晦。现代代码中,除非维护老系统或对接旧接口,否则应直接用 java.time 类型。
-
LocalDate.plusMonths(1)行为明确:1 月 31 日 → 2 月 28 日(非异常) -
ZonedDateTime.withEarlierOffsetAtOverlap()显式控制 DST 重叠行为 -
Duration和Period分离了“时间量”与“日历量”,避免混淆
LocalDate date = LocalDate.of(2025, 1, 31);
LocalDate nextMonth = date.plusMonths(1); // 2025-02-28
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Europe/Berlin"));
ZonedDateTime tomorrow = zdt.plusDays(1); // 自动处理 DST
用 Calendar 做跨月加减时,务必确认 lenient 模式和时区设置;如果逻辑涉及 DST、长期调度或需要不可变语义,java.time 不是“升级选项”,而是唯一合理选择。
# java
# go
# 为什么
# jvm
# date
# Calendar
# 接口
# 线程
# 对象
# 很多人
# 仍是
# 不存在
# 到你
# 问题是
# 只在
# 报错
# 跳到
# 最容易
# 个月
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】
青岛网站建设如何选择本地服务器?
🚀拖拽式CMS建站能否实现高效与个性化并存?
bootstrap日历插件datetimepicker使用方法
悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
如何基于PHP生成高效IDC网络公司建站源码?
Windows10如何更改计算机工作组_Win10系统属性修改Workgroup
手机网站制作与建设方案,手机网站如何建设?
JavaScript如何实现错误处理_try...catch如何捕获异常?
PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
Linux网络带宽限制_tc配置实践解析【教程】
使用C语言编写圣诞表白程序
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?
详解CentOS6.5 安装 MySQL5.1.71的方法
详解jQuery中的事件
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
Android中AutoCompleteTextView自动提示
php485函数参数是什么意思_php485各参数详细说明【介绍】
Java类加载基本过程详细介绍
大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?
iOS UIView常见属性方法小结
企业网站制作这些问题要关注
Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作
网站制作报价单模板图片,小松挖机官方网站报价?
如何用AI帮你把自己的生活经历写成一个有趣的故事?
如何快速搭建高效香港服务器网站?
Laravel怎么实现模型属性的自动加密
微信小程序 require机制详解及实例代码
绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信
如何在宝塔面板中修改默认建站目录?
教你用AI将一段旋律扩展成一首完整的曲子
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
php增删改查怎么学_零基础入门php数据库操作必知基础【教程】
零服务器AI建站解决方案:快速部署与云端平台低成本实践
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
Laravel模型关联查询教程_Laravel Eloquent一对多关联写法
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
如何在IIS中新建站点并配置端口与IP地址?
香港服务器网站卡顿?如何解决网络延迟与负载问题?


