news 2026/2/10 8:16:44

java学习--Calendar

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java学习--Calendar

一、Calendar 类核心定位与核心特性

✅ 1. 核心作用

java.util.Calendar是 Java 提供的日期时间「操作与计算」工具类,是 JDK 1.1 推出的Date类的替代增强方案—— 解决了Date类直接操作年 / 月 / 日 / 时 / 分 / 秒繁琐、方法大量过时的问题,专门负责日期字段的获取、设置、增减计算

✅ 2. 核心特性(必知)

  1. 抽象类,不能直接 new:Calendar 是抽象父类,需通过静态方法Calendar.getInstance()获取子类(GregorianCalendar,公历)对象;
  2. 默认表示当前系统时间:调用getInstance()得到的对象,默认封装了「当前电脑的日期 + 时间」;
  3. 字段索引化:通过预定义的静态常量(如YEARMONTH)操作年、月、日等字段,而非直接调用方法;
  4. 存在设计缺陷:月份从0开始、星期从1开始,是最易踩坑的点;
  5. 线程不安全:与DateSimpleDateFormat一致,多线程环境下共享实例会有并发风险;
  6. 过渡型 API:JDK 1.8 推出的java.time新日期 API(LocalDate/LocalDateTime)完全替代它,新项目优先用新 API,老项目兼容时用 Calendar

二、Calendar 核心使用步骤(通用)

Calendar 的所有操作都遵循「获取对象 → 操作字段 → 结果处理」三步,是固定套路,务必牢记:

import java.util.Calendar; public class CalendarBase { public static void main(String[] args) { // 1. 核心:获取Calendar实例(唯一方式,不能new Calendar()) Calendar cal = Calendar.getInstance(); // 2. 核心操作:获取/设置/增减 年、月、日、时、分、秒等字段 int year = cal.get(Calendar.YEAR); // 获取年份 cal.set(Calendar.MONTH, 11); // 设置月份为12月 cal.add(Calendar.DAY_OF_MONTH, 7); // 日期加7天 // 3. 结果转换:转Date对象 / 格式化输出 java.util.Date date = cal.getTime(); System.out.println("转换后的Date对象:" + date); } }

三、Calendar 三大核心操作(全示例 + 详解)

✅ 操作 1:获取日期字段(get 方法)—— 最常用

通过int get(int field)方法,传入 Calendar 预定义的字段常量,获取指定的日期 / 时间数值,这是 Calendar 最基础的用法。

✔️ 常用字段常量(必须熟记)
常量名含义取值范围 / 注意事项
Calendar.YEAR年份4 位完整年份(如 2025,无偏移,直接用)
Calendar.MONTH月份✅【核心坑点】0~11(0=1 月、1=2 月...11=12 月)
Calendar.DAY_OF_MONTH当月日期1~31(对应日历中的「几号」,最常用)
Calendar.HOUR_OF_DAY24 小时制小时0~23(推荐,业务开发通用)
Calendar.HOUR12 小时制小时0~11
Calendar.MINUTE分钟0~59
Calendar.SECOND0~59
Calendar.MILLISECOND毫秒0~999
Calendar.DAY_OF_WEEK星期✅【坑点】1~7(1 = 周日、2 = 周一...7 = 周六)
✔️ 完整获取示例代码
import java.util.Calendar; public class CalendarGet { public static void main(String[] args) { // 获取Calendar实例(当前时间) Calendar cal = Calendar.getInstance(); // 获取核心字段 int year = cal.get(Calendar.YEAR); // 月份修正:+1 才是实际月份(因为Calendar月份从0开始) int month = cal.get(Calendar.MONTH) + 1; int day = cal.get(Calendar.DAY_OF_MONTH); int hour = cal.get(Calendar.HOUR_OF_DAY); int minute = cal.get(Calendar.MINUTE); int second = cal.get(Calendar.SECOND); // 星期修正:1=周日,需转换为业务常用的「周一~周日」 int week = cal.get(Calendar.DAY_OF_WEEK); String weekStr = switch (week) { case 1 -> "周日"; case 2 -> "周一"; case 3 -> "周二"; case 4 -> "周三"; case 5 -> "周四"; case 6 -> "周五"; case 7 -> "周六"; default -> ""; }; // 格式化输出 System.out.printf("当前时间:%d年%d月%d日 %02d:%02d:%02d %s%n", year, month, day, hour, minute, second, weekStr); } }

✅ 关键提醒:月份和星期必须做修正,否则会出现「1 月显示 0、12 月显示 11、周日显示 1」的错误,这是 Calendar 最高频的坑!

✅ 操作 2:设置日期字段(set 方法)—— 两种方式

通过set方法可以精准修改指定字段的值,支持「单字段设置」和「多字段批量设置」,满足任意自定义日期的需求,修改后 Calendar 对象的时间会同步更新。

✔️ 方式 1:单字段设置void set(int field, int value)
Calendar cal = Calendar.getInstance(); // 设置年份为2026 cal.set(Calendar.YEAR, 2026); // 设置月份为3月(注意:传入2,因为0=1月) cal.set(Calendar.MONTH, 2); // 设置日期为15号 cal.set(Calendar.DAY_OF_MONTH, 15); // 设置小时为18点(24小时制) cal.set(Calendar.HOUR_OF_DAY, 18); System.out.println("设置后时间:" + cal.getTime());
✔️ 方式 2:批量设置void set(int year, int month, int day[, int hour, int minute, int second])

一次性设置年、月、日(可选时分秒),最简洁高效,推荐使用:

Calendar cal = Calendar.getInstance(); // 批量设置:2025年12月25日 20:00:00(月份传11,对应12月) cal.set(2025, 11, 25, 20, 0, 0); System.out.println("批量设置后:" + cal.getTime());

✅ 操作 3:增减日期计算(add 方法)—— 核心亮点

void add(int field, int amount)是 Calendar 最核心的优势方法,专门用于日期的偏移计算(加 / 减年、月、日、时等),自动处理「跨月、跨年、闰年」等边界情况,无需手动计算。

  • amount > 0:字段增加对应数值
  • amount < 0:字段减少对应数值
✔️ 完整计算示例代码(开发高频场景)
import java.util.Calendar; import java.util.Date; public class CalendarAdd { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); System.out.println("原始时间:" + now); // 1. 加1年 cal.add(Calendar.YEAR, 1); System.out.println("加1年:" + cal.getTime()); cal.add(Calendar.YEAR, -1); // 还原 // 2. 减2个月 cal.add(Calendar.MONTH, -2); System.out.println("减2个月:" + cal.getTime()); cal.add(Calendar.MONTH, 2); // 还原 // 3. 加7天(计算1周后,开发高频) cal.add(Calendar.DAY_OF_MONTH, 7); System.out.println("加7天:" + cal.getTime()); cal.add(Calendar.DAY_OF_MONTH, -7); // 还原 // 4. 减3小时 cal.add(Calendar.HOUR_OF_DAY, -3); System.out.println("减3小时:" + cal.getTime()); // ✅ 自动处理边界:2025-01-01 减1天 → 2024-12-31 cal.set(2025, 0, 1); cal.add(Calendar.DAY_OF_MONTH, -1); System.out.println("边界处理示例:" + cal.getTime()); } }

✅ 核心优势:add方法是 Calendar 相比 Date 的最大亮点,彻底解决了手动计算日期的繁琐和错误风险

四、Calendar 与 Date 互转(开发必备)

实际开发中,Calendar 负责「日期计算」,Date 负责「表示时间瞬间」,二者经常需要互相转换,转换逻辑是开发高频考点,必须熟练掌握。

✅ 1. Calendar → Date

调用 Calendar 的Date getTime()方法,直接返回对应的 Date 对象,无参数、无异常,极简:

Calendar cal = Calendar.getInstance(); // Calendar 转 Date Date date = cal.getTime();

✅ 2. Date → Calendar

调用 Calendar 的void setTime(Date date)方法,将 Date 对象的时间赋值给 Calendar,无返回值、无异常

Date date = new Date(); Calendar cal = Calendar.getInstance(); // Date 转 Calendar cal.setTime(date);

✅ 完整互转示例

import java.util.Calendar; import java.util.Date; public class CalendarDateConvert { public static void main(String[] args) { // ========== Calendar → Date ========== Calendar cal1 = Calendar.getInstance(); cal1.set(2025, 11, 29); // 2025-12-29 Date date1 = cal1.getTime(); System.out.println("Calendar转Date:" + date1); // ========== Date → Calendar ========== Date date2 = new Date(); // 当前时间 Calendar cal2 = Calendar.getInstance(); cal2.setTime(date2); System.out.printf("Date转Calendar:%d年%d月%d日%n", cal2.get(Calendar.YEAR), cal2.get(Calendar.MONTH)+1, cal2.get(Calendar.DAY_OF_MONTH)); } }

五、Calendar 格式化(转指定格式字符串)

Calendar 本身不具备格式化能力,和 Date 一样,需要配合格式化工具类完成「Calendar → 自定义格式字符串」的转换,主流两种方案:

✅ 方案 1:Calendar + SimpleDateFormat(传统方案,兼容所有 JDK)

核心逻辑:Calendar → Date → 格式化字符串

import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class CalendarFormat { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); Date date = cal.getTime(); // 先转Date // 定义格式:yyyy-MM-dd HH:mm:ss SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 格式化 String dateStr = sdf.format(date); System.out.println("格式化结果:" + dateStr); // 示例:2025-12-29 16:30:50 } }

✅ 方案 2:Calendar → JDK8 新 API → DateTimeFormatter(推荐,线程安全)

JDK8 推出的DateTimeFormatter线程安全、无并发风险,是当前开发首选,转换逻辑:Calendar → Date → Instant → LocalDateTime → 格式化

import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; public class CalendarNewFormat { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); Date date = cal.getTime(); // 1. Date → LocalDateTime LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); // 2. 定义格式化器(线程安全) DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 3. 格式化 String dateStr = dtf.format(ldt); System.out.println("JDK8格式化结果:" + dateStr); } }

六、Calendar 高频坑点 & 注意事项(避坑宝典)

这部分是重中之重,Calendar 的设计缺陷导致坑点极多,也是面试高频考点,务必全部掌握,杜绝开发 BUG!

❌ 坑点 1:月份从 0 开始(最高频)

✅ 现象:Calendar.JANUARY = 0Calendar.DECEMBER = 11,直接获取 / 设置会少 1 个月;✅ 解决方案:获取时 + 1,设置时 - 1;✅ 示例:设置 3 月 → 传入 2,获取到 2 → 表示 3 月。

❌ 坑点 2:星期从 1 开始,且 1 代表周日(次高频)

✅ 现象:Calendar.SUNDAY =1Calendar.SATURDAY=7,与业务中「周一 = 1、周日 = 7」不符;✅ 解决方案:获取后通过switch/if转换为业务常用格式。

❌ 坑点 3:Calendar 是线程不安全的

✅ 现象:多线程环境下共享同一个 Calendar 实例,调用set/add方法会导致日期错乱;✅ 解决方案:① 每个线程独立创建Calendar 实例;② 新项目直接用 JDK8 新日期 API(线程安全)。

❌ 坑点 4:add 与 roll 方法混淆(易误用)

Calendar 有两个偏移方法:addroll99% 的场景用 add,二者核心区别:

  • add(int field, int amount)联动其他字段(推荐),例如 2025-12-31 加 1 天 → 2026-01-01;
  • roll(int field, int amount)不联动其他字段,仅修改当前字段,例如 2025-12-31 加 1 天 → 2025-12-01(开发极少用)。

❌ 坑点 5:getTime () 与 getTimeInMillis () 混淆

  • getTime():返回Date 对象,用于格式转换、Date 互转;
  • getTimeInMillis():返回时间戳(long 型,毫秒),用于时间比较、跨语言传输。

七、Calendar vs Date vs JDK8 新 API(选型指南)

很多同学会疑惑三者的区别和选型,这里给出清晰的对比和开发建议,直接套用即可:

✅ 三者核心区别

类 / API定位优点缺点
Date表示「时间瞬间」简单、轻量,仅表示时间点方法大量过时,无计算 / 格式化能力
Calendar日期「操作 / 计算」工具支持字段获取、设置、增减,自动处理边界设计缺陷多(月 0 周 1)、线程不安全、API 繁琐
java.time(JDK8)新一代日期时间 API✅线程安全 ✅无设计缺陷 ✅API 优雅 ✅支持时区 / 闰年JDK8 及以上版本可用(目前项目均满足)

✅ 开发选型建议(强制遵循)

  1. 新项目 / 技术升级项目直接使用 JDK8 新日期 API(LocalDate/LocalDateTime/Instant),彻底抛弃 Date + Calendar,开发效率翻倍,无坑点;
  2. 老项目维护:需兼容 Date/Calendar 时,用 Calendar 做日期计算,用 Date 表示时间点,用 SimpleDateFormat 做格式化,严格规避上述坑点;
  3. 核心原则能不用 Calendar 就不用,它只是 Date 的过渡方案,并非最优解。

八、核心知识点总结

  1. Calendar抽象类,唯一获取实例的方式是Calendar.getInstance()
  2. Calendar 核心能力:字段获取(get)、字段设置(set)、日期计算(add),是 Date 的增强工具;
  3. 两大致命坑点:月份 0 开始、星期 1 = 周日,必须做修正;
  4. Calendar 与 Date 互转:getTime()(Cal→Date)、setTime(Date)(Date→Cal);
  5. Calendar 无格式化能力,需配合 SimpleDateFormat/DateTimeFormatter;
  6. 终极建议:JDK8+ 项目优先使用java.time新 API,Calendar 仅用于老项目兼容。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 0:09:27

PyTorch-CUDA-v2.7镜像如何配合VS Code远程开发

PyTorch-CUDA-v2.7 镜像与 VS Code 远程开发的高效协同实践 在深度学习项目日益复杂的今天&#xff0c;一个稳定、一致且高效的开发环境已成为团队能否快速迭代的核心前提。然而&#xff0c;现实往往并不理想&#xff1a;有人因为 CUDA 版本不匹配导致 torch.cuda.is_available…

作者头像 李华
网站建设 2026/2/8 18:07:23

巨型模型训练的近乎线性扩展技术

状态最先进的语言模型拥有数十亿参数。在可控时间内训练这些模型需要将工作负载分配到大型计算集群上。理想情况下&#xff0c;训练时间应随着集群规模的扩大而线性减少。然而&#xff0c;线性扩展很难实现&#xff0c;因为协调集群节点工作所需的通信消耗了并行化带来的增益。…

作者头像 李华
网站建设 2026/2/7 2:27:46

8款免费AI论文工具实测:半天生成25000字计算机论文+真实参考文献

还在为论文熬夜、秃头、抓狂吗&#xff1f;告别低效苦熬&#xff0c;拥抱AI赋能的高效科研新时代。这篇文章将为你实测8款强大的免费AI论文工具&#xff0c;从文献检索到初稿生成&#xff0c;从深度改写到最后润色&#xff0c;手把手教你如何利用这些“神器”&#xff0c;真正实…

作者头像 李华
网站建设 2026/2/6 17:03:21

PyTorch-CUDA-v2.7镜像中利用‘jupyter notebook’高搜索量做引流

PyTorch-CUDA-v2.7 镜像中的 Jupyter Notebook&#xff1a;从开发效率到技术引流的双重价值 在深度学习项目中&#xff0c;最让人头疼的往往不是模型设计本身&#xff0c;而是环境搭建——“为什么我的代码在别人机器上跑不通&#xff1f;”、“CUDA 版本不匹配怎么办&#xff…

作者头像 李华
网站建设 2026/2/7 19:40:43

Elasticsearch的深度翻页问题

使用ES做搜索引擎拉取数据的时候&#xff0c;如果数据量太大&#xff0c;通过传统的from size的方式并不能获取所有的数据&#xff08;默认最大记录数10000&#xff09;&#xff0c;因为随着页数的增加&#xff0c;会消耗大量的内存&#xff0c;导致ES集群不稳定。 ES提供了3…

作者头像 李华
网站建设 2026/2/8 17:22:53

PyTorch-CUDA-v2.7镜像如何启用梯度检查点功能

PyTorch-CUDA-v2.7镜像中梯度检查点的高效启用实践 在训练大规模Transformer模型时&#xff0c;你是否曾因“CUDA out of memory”错误而被迫减小batch size&#xff1f;又或者在新服务器上花费数小时配置PyTorch和CUDA版本兼容问题&#xff1f;这些问题在当前大模型研发中极为…

作者头像 李华