You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Calendar类月份设置出现异常不一致现象

问题原因详解

这个问题其实是Java Calendar类的两个经典特性在“搞鬼”——0-based的月份索引,加上它特有的延迟计算+自动日期调整机制,咱们一步步拆解来看:

1. 先搞懂Calendar的月份计数

首先得明确一个容易踩坑的点:Calendar的月份是从0开始计数的!Calendar.JANUARY对应0,Calendar.FEBRUARY对应1,Calendar.MARCH对应2……所以你代码里写的set(Calendar.MONTH, 1),设置的是二月,不是一月。

2. 延迟计算+宽松模式的自动调整

Calendar默认是宽松模式,而且采用延迟计算逻辑:当你调用set()修改字段时,它不会立刻更新整个日历的时间戳,只有当你调用get()、getTime()这类需要读取实际日期的方法时,才会统一计算并处理无效的日期。

咱们把你的代码执行流程拆解开(假设当前系统日期是有31天的月份,比如3月31日):

  • 第一步:Calendar.getInstance()拿到当前日期:202X年3月31日。
  • 第一次调用calendar.set(Calendar.MONTH, 1):只是把月份字段标记为1(二月),但Calendar此时不会校验日期是否合法。
  • 第一次调用calendar.get(Calendar.MONTH):触发日期计算逻辑。这时候它发现,当前的日是31,但二月最多只有28或29天(平年28,闰年29),这个日期无效。在宽松模式下,Calendar会自动“修复”这个日期:把月份加1(变成三月,对应索引2),然后用31减去二月的最大天数(比如28),得到3,最终日期变成202X年3月3日。所以这时候get(MONTH)返回的是2。
  • 第二次调用calendar.set(Calendar.MONTH, 1):此时Calendar的当前日期是3月3日,设置月份为1(二月),二月肯定有3号,这个日期完全合法。
  • 第二次调用calendar.get(Calendar.MONTH):计算后日期是202X年2月3日,月份索引是1,所以返回1。

如何避免这类坑?

如果你想严格控制日期,不想让它偷偷调整,可以关闭宽松模式:

calendar.setLenient(false);

这样当你设置无效日期时,会直接抛出IllegalArgumentException,而不是默默调整。另外,更推荐你使用Java 8及以后的java.time包(比如LocalDate、Month枚举),这些类的设计更直观,没有0-based月份的坑,也不会有这种隐式的日期调整问题,代码可读性和安全性都高很多。


内容的提问来源于stack exchange,提问作者redochka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:42:19