calendar.getinstance() 返回 jvm 默认时区的实例,月份字段 calendar.month 取值为 0–11,需加 1 才得自然月;推荐使用 java 8+ 的 localdate 替代,其 api 更直观安全,android 低版本需注意兼容性与时区数据完整性。

Calendar.getInstance() 返回的是当前时区的日期对象
直接调用 Calendar.getInstance() 得到的是 JVM 默认时区下的日历实例,不是 UTC,也不是“系统时间”抽象值。如果你在东八区服务器上运行,它默认就按北京时间解析;换到美国服务器,get(Calendar.YEAR) 可能返回前一天的年份(尤其在深夜跨日时)。别假设它“天然准确”,得先确认时区意图。
用 get() 方法提取年月日要小心月份从 0 开始
Calendar.MONTH 的取值是 0–11,不是 1–12。这是最常踩的坑:把 cal.get(Calendar.MONTH) 直接当“几月”用,结果 3 月输出成 2。其他字段如 YEAR、DAY_OF_MONTH 都是直观值,唯独月份例外。
常见写法示例:
Calendar cal = Calendar.getInstance(); int year = cal.get(Calendar.YEAR); // ✅ 正确,如 2024 int month = cal.get(Calendar.MONTH) + 1; // ✅ 加 1 才是真实月份 int day = cal.get(Calendar.DAY_OF_MONTH); // ✅ 正确,如 5
Calendar 已过时,优先用 LocalDate(Java 8+)
Calendar 类设计陈旧,线程不安全,API 混乱(比如 DAY_OF_YEAR 和 DATE 容易混淆),且无法表达“纯日期”概念(它总带时分秒和时区)。现代代码应改用 LocalDate:
-
LocalDate.now()默认用系统时钟 + 默认时区,行为更可预测 -
LocalDate.now(ZoneId.of("Asia/Shanghai"))显式指定时区,避免环境漂移 - 获取字段直接用
getYear()、getMonthValue()、getDayOfMonth(),全部是自然数
如果必须兼容老 JDK,至少封装一层屏蔽 MONTH 偏移:
public static int getRealMonth(Calendar cal) {
return cal.get(Calendar.MONTH) + 1;
}
Android 上注意 API 级别和替代方案
Android 26+(Android O)才完整支持 java.time,低版本仍需用 Calendar。但要注意:Calendar.getInstance(TimeZone.getTimeZone("UTC")) 在某些旧机型上可能因时区数据缺失返回错误结果。更稳妥的做法是用 System.currentTimeMillis() 配合 SimpleDateFormat(仅限 UI 展示)或引入 ThreeTenABP 库补全 JSR-310。
另外,Calendar.get(Calendar.DAY_OF_WEEK) 返回的是星期几(周日=1),和 LocalDate.getDayOfWeek().getValue()(周一=1)也不一致——这种隐式约定差异,容易在跨平台同步逻辑里埋雷。
真正麻烦的从来不是“怎么取三个数字”,而是这些数字代表的时间语义是否稳定、可预期。尤其当你的代码要跑在 Docker 容器、云函数或用户手机上时,时区、JDK 版本、系统时间源都可能悄悄改变结果。










