在Java里Calendar类如何进行日期计算_Java时间操作说明

发布时间 - 2026-02-01 00:00:00    点击率:
Calendar.add()是日期计算主力方法,自动处理进位越界;roll()仅在当前单位内滚动不改变更大单位;set()需调用getTime()等才生效;Calendar线程不安全且已过时,但部分场景仍需谨慎使用。

Calendar.add() 是日期计算的主力方法

直接用 add() 方法增减年、月、日等字段,它会自

动处理进位和越界(比如 1 月加 12 个月变成下一年 1 月,2 月 30 日会回滚到 3 月 2 日)。别手写毫秒加减再转回 Calendar —— 容易出错且不跨时区安全。

常见错误是传错字段常量:Calendar.MONTH 是从 0 开始的(0 表示 1 月),而 Calendar.DAY_OF_MONTHCalendar.YEAR 是从 1 或自然年份开始的。加 1 个月 ≠ 加 30 天,尤其遇到 1 月、2 月、闰年时结果差异明显。

  • 加 3 天:calendar.add(Calendar.DAY_OF_MONTH, 3)
  • 减 1 年:calendar.add(Calendar.YEAR, -1)
  • 加 2 个月(注意:不是固定天数):calendar.add(Calendar.MONTH, 2)

Calendar.roll() 和 add() 的关键区别在哪

roll() 只在当前单位内“滚动”,不改变更大单位。比如对 2025-01-31 调用 roll(Calendar.MONTH, 1),结果是 2025-02-28(不是 2025-02-31,也不变成 2025-02-31 再进位到 3 月),年份不会变;而 add(Calendar.MONTH, 1) 会得到 2025-02-28,但如果是 2025-01-15,则两者结果一致。

适用场景很窄:仅当明确需要“不溢出上级单位”时才用 roll(),例如做月份选择器只在 1–12 间循环,或调试时临时调整某字段观察局部影响。

  • 想让“2025-12-15 + 1 月”变成 2025-01-15?必须用 add()
  • 想让“12 月”按 +1 滚成 “1 月”,但年份卡死在 2025?才考虑 roll(Calendar.MONTH, 1)
  • roll()Calendar.DAY_OF_YEAR 等字段行为也受限,别默认它和 add() 等价

为什么 set() 后要调用 getTime() 或 computeTime() 才生效

set() 方法只是把字段值记下来,并不立即重算时间戳(time 字段),直到你调用 getTime()get()computeTime() 才真正触发计算。这导致一个经典陷阱:连续 set() 多个字段后直接 getTimeInMillis(),可能拿到未同步的旧时间戳。

更隐蔽的问题是字段冲突:比如先 set(Calendar.MONTH, 1)(2 月),再 set(Calendar.DAY_OF_MONTH, 30),这时 2 月没有 30 日,但 Calendar 不会立刻报错或修正——它等到真正计算时才按规则回滚(变成 3 月 2 日),而这个时机不可控。

  • 安全做法:每次 set() 后,如需立刻获取时间值,紧跟 calendar.getTime()
  • 避免混合使用 set()add():前者延迟计算,后者立即更新内部状态,混用易引发时序 bug
  • 如果只是初始化 Calendar,优先用 GregorianCalendar(int year, int month, int day) 构造器,比多次 set() 更可靠

Calendar 在 Java 8+ 中已被弃用,但有些场景绕不开

虽然 java.time(如 LocalDateTimeZonedDateTime)是推荐替代方案,但仍有现实约束:老系统接口返回 Calendar、某些 Android API(尤其是低于 API 26 的版本)、遗留数据库驱动(如旧版 JDBC)仍以 Calendar 传时区时间。硬切 java.time 可能引入兼容性风险或额外转换开销。

若必须用 Calendar,务必注意:它的线程不安全,不能复用实例;SimpleDateFormat 配合 Calendar 解析时,时区行为依赖 Calendar.getTimeZone(),而非格式字符串里的 Z 或 z;Android 上部分机型对 Calendar.getInstance(TimeZone) 的夏令时支持不一致。

  • 多线程环境:每次用都 new 一个 GregorianCalendar(),别共享 static 实例
  • java.time 互转:用 GregorianCalendar.from(ZonedDateTime)calendar.toInstant().atZone(ZoneId.systemDefault()),别用毫秒戳中转丢失时区信息
  • Android 开发者注意:Calendar.getActualMaximum(Calendar.DAY_OF_MONTH) 在某些厂商 ROM 上对 2 月返回错误值,建议用 YearMonth.of(year, month).lengthOfMonth() 替代
实际项目里,最常被忽略的是字段索引偏移(MONTH=0)、set() 的延迟求值机制,以及跨月计算时对“月末日”的隐式处理逻辑——这些细节不写测试很难暴露,一到生产环境就出错。


# java  # android  # go  # 区别  # 为什么  # lmax  # Static  # 常量  # Calendar  # 字符串  # int  # 循环  # 接口  # 线程  # 多线程  # 选择器  # 数据库  # bug  # 个月  # 更大  # 是从  # 只在  # 想让  # 时才  # 不安全  # 不改变  # 的是  # 也不 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何解决hover在ie6中的兼容性问题  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  如何实现javascript表单验证_正则表达式有哪些实用技巧  Laravel怎么自定义错误页面_Laravel修改404和500页面模板  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  EditPlus中的正则表达式实战(6)  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  晋江文学城电脑版官网 晋江文学城网页版直接进入  Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转  教你用AI将一段旋律扩展成一首完整的曲子  免费视频制作网站,更新又快又好的免费电影网站?  如何挑选优质建站一级代理提升网站排名?  如何制作一个表白网站视频,关于勇敢表白的小标题?  Firefox Developer Edition开发者版本入口  linux写shell需要注意的问题(必看)  如何快速查询域名建站关键信息?  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  米侠浏览器网页背景异常怎么办 米侠显示修复  Win11关机界面怎么改_Win11自定义关机画面设置【工具】  开心动漫网站制作软件下载,十分开心动画为何停播?  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  如何打造高效商业网站?建站目的决定转化率  Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧  Android仿QQ列表左滑删除操作  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  C语言设计一个闪闪的圣诞树  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  Laravel如何实现多对多模型关联?(Eloquent教程)  Laravel如何生成API文档?(Swagger/OpenAPI教程)  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  如何在景安云服务器上绑定域名并配置虚拟主机?  LinuxShell函数封装方法_脚本复用设计思路【教程】  Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践  深入理解Android中的xmlns:tools属性  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  如何用AWS免费套餐快速搭建高效网站?  PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑  公司门户网站制作流程,华为官网怎么做?  零服务器AI建站解决方案:快速部署与云端平台低成本实践  Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理  Laravel怎么在Controller之外的地方验证数据  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  PythonWeb开发入门教程_Flask快速构建Web应用  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】