杰瑞科技汇

Java的Calendar时间处理怎么用?

Calendar 是 Java 早期处理日期和时间的一个核心类,它位于 java.util 包中,虽然现在 Java 8 引入了更现代、更易用的 java.time 包,但 Calendar 仍然在许多遗留代码中被广泛使用,因此理解它非常重要。

Java的Calendar时间处理怎么用?-图1
(图片来源网络,侵删)

Calendar 类的核心思想

Calendar 是一个抽象类,它不表示一个具体的时间点,而是代表一个“日历系统”,它提供了很多方法来操作日期和时间的各个部分(如年、月、日、时、分、秒等)。

获取 Calendar 实例

由于 Calendar 是抽象类,我们不能直接 new 它,必须使用其静态工厂方法 getInstance() 来获取一个实例。

import java.util.Calendar;
public class CalendarExample {
    public static void main(String[] args) {
        // 获取一个表示当前日期和时间的 Calendar 实例
        Calendar calendar = Calendar.getInstance();
        System.out.println("当前 Calendar 对象: " + calendar);
        // 输出示例: 当前 Calendar 对象: java.util.GregorianCalendar[time=1678886400000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=235,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2025,MONTH=2,WEEK_OF_YEAR=11,WEEK_OF_MONTH=2,DAY_OF_MONTH=14,DAY_OF_YEAR=74,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=10,HOUR_OF_DAY=10,MINUTE=40,SECOND=0,MILLISECOND=0,ZONE_OFFSET=28800000,DST_OFFSET=0]
    }
}

从输出可以看到,Calendar 对象内部包含了非常丰富的信息,包括时间戳、各个时间字段的值、时区等。

Calendar 的重要字段

Calendar 使用一组常量来表示日期和时间的各个部分,这些常量是 Calendar 类的静态成员。

Java的Calendar时间处理怎么用?-图2
(图片来源网络,侵删)
常量 含义 备注
YEAR
MONTH 重要:从 0 开始计数 (0=一月, 1=二月, ..., 11=十二月)
DAY_OF_MONTH 月中的第几天 (1-31)
DAY_OF_YEAR 年中的第几天 (1-366)
HOUR 小时 (12小时制) (0-11)
HOUR_OF_DAY 小时 (24小时制) (0-23)
MINUTE 分钟 (0-59)
SECOND (0-59)
MILLISECOND 毫秒 (0-999)
AM_PM 上午/下午 Calendar.AM (0) 或 Calendar.PM (1)
DAY_OF_WEEK 星期几 重要:从 1 开始计数 (1=星期日, 2=星期一, ..., 7=星期六)
WEEK_OF_YEAR 年中的第几周
WEEK_OF_MONTH 月中的第几周

常用操作

获取日期时间字段

使用 get(int field) 方法来获取指定字段的值。

Calendar calendar = Calendar.getInstance();
// 获取年
int year = calendar.get(Calendar.YEAR);
System.out.println("年份: " + year); // 输出: 2025
// 获取月 (注意:需要 +1)
int month = calendar.get(Calendar.MONTH) + 1;
System月份: " + month); // 输出: 3 (如果当前是三月)
// 获取日
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("日: " + day); // 输出: 14
// 获取小时 (24小时制)
int hour = calendar.get(Calendar.HOUR_OF_DAY);
System.out.println("小时: " + hour);
// 获取星期几 (注意:1是星期日)
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println("星期几 (1=星期日): " + dayOfWeek);

设置日期时间

使用 set(int field, int value) 方法来设置某个字段的值。

Calendar calendar = Calendar.getInstance();
// 设置年为 2025
calendar.set(Calendar.YEAR, 2025);
// 设置月为 9 (代表十月)
calendar.set(Calendar.MONTH, 9);
// 设置日为 1
calendar.set(Calendar.DAY_OF_MONTH, 1);
// 也可以一次性设置年月日
// calendar.set(2025, Calendar.OCTOBER, 1);
System.out.println("设置后的日期: " + calendar.getTime());
// 输出: 设置后的日期: Wed Oct 01 10:40:00 CST 2025

时间计算 (核心功能)

Calendar 最强大的功能之一就是进行时间的加减操作。

  • add(int field, int amount): 在指定字段上增加或减少一个值,同时会向上或向下进位。
    • MONTH 字段上加 1,如果当前是 12 月,年份会自动加 1,月份变为 1 月。
  • roll(int field, int amount): 在指定字段上增加或减少一个值,但不会影响更大的时间单位
    • MONTH 字段上加 1,如果当前是 12 月,年份不会改变,月份会变成 1 月(类似于循环)。

示例:add() 方法

Java的Calendar时间处理怎么用?-图3
(图片来源网络,侵删)
Calendar calendar = Calendar.getInstance();
System.out.println("当前时间: " + calendar.getTime());
// 增加 3 个月
calendar.add(Calendar.MONTH, 3);
System.out.println("增加3个月后: " + calendar.getTime());
// 减少 5 天
calendar.add(Calendar.DAY_OF_MONTH, -5);
System.out.println("减少5天后: " + calendar.getTime());
// 增加 1 年
calendar.add(Calendar.YEAR, 1);
System.out.println("增加1年后: " + calendar.getTime());

示例:roll() 方法

Calendar calendar = Calendar.getInstance();
// 假设当前是 2025年10月31日
calendar.set(2025, Calendar.OCTOBER, 31);
System.out.println("初始时间: " + calendar.getTime()); // Tue Oct 31 10:40:00 CST 2025
// roll 增加 3 个月 (年份不会变)
calendar.roll(Calendar.MONTH, 3);
System.out.println("roll增加3个月后: " + calendar.getTime()); // Tue Jan 31 10:40:00 CST 2025
// 月份从10月 -> 1月,但年份仍然是2025

获取 Date 对象

Calendarjava.util.Date 可以互相转换。

  • calendar.getTime(): 将 Calendar 对象转换为 Date 对象。
  • calendar.setTime(Date date): 用一个 Date 对象来设置 Calendar
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
System.out.println("从 Calendar 获取的 Date: " + date);
// 输出: 从 Calendar 获取的 Date: Tue Mar 14 10:40:00 CST 2025

Calendar 的主要缺点

正是因为 Calendar 存在一些明显的设计缺陷,Java 8 才推出了全新的 java.time API。

  1. 月份从 0 开始:这是最常见的“陷阱”,开发者很容易忘记 MONTH 字段需要 +1 才能得到实际的月份。
  2. 星期几从 1 开始 (星期日):与人们的日常习惯(周一为第一天)不符,容易混淆。
  3. 可变性Calendar 对象是可变的,一旦创建,你就可以直接修改它的状态,这在并发环境下是不安全的,也使得代码难以维护。
  4. API 设计笨拙:很多操作(如加减时间)需要理解 addroll 的细微差别,API 不够直观。
  5. 线程不安全Calendar 实例不能在多线程环境中安全共享。

java.time API 的对比 (现代推荐)

如果你使用的是 Java 8 或更高版本,强烈推荐使用 java.time中的类,它们更直观、更安全、功能更强大。

功能 java.util.Calendar java.time (推荐)
表示日期 Calendar LocalDate
表示时间 Calendar LocalTime
表示日期时间 Calendar LocalDateTime
获取当前时间 Calendar.getInstance() LocalDateTime.now()
获取年/月/日 get(Calendar.YEAR) getYear() / getMonthValue() / getDayOfMonth()
设置日期 set(year, month, day) of(year, month, day)withYear()
时间计算 add(field, amount) plusDays(1), minusMonths(2) 等,非常直观
不可变性 可变 不可变 (线程安全)
月份 0-11 1-12 (符合直觉)
星期 1-7 (1=周日) 1-7 (1=周一, 7=周日)

java.time 示例:

import java.time.LocalDateTime;
import java.time.LocalDate;
public class ModernTimeExample {
    public static void main(String[] args) {
        // 获取当前日期时间
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前日期时间: " + now);
        // 获取年月日,API非常清晰
        int year = now.getYear();
        int month = now.getMonthValue(); // 直接是 1-12
        int day = now.getDayOfMonth();
        System.out.printf("年: %d, 月: %d, 日: %d%n", year, month, day);
        // 创建特定日期
        LocalDate date = LocalDate.of(2025, 10, 1);
        System.out.println("特定日期: " + date);
        // 时间计算,API非常直观
        LocalDateTime future = now.plusDays(5).minusMonths(1);
        System.out.println("5天后减去1个月: " + future);
    }
}

特性 java.util.Calendar java.time (Java 8+)
状态 可变 不可变
线程安全 不安全 线程安全
API 直观性 较差,有陷阱 非常好,符合直觉
月份 0-11 1-12
星期 1-7 (1=周日) 1-7 (1=周一)
推荐场景 维护旧代码 所有新项目
  • 学习 Calendar:为了理解和维护 Java 8 之前的旧代码。
  • 使用 java.time:进行所有新的日期时间开发,它是 Java 未来的标准,也是更优的选择。
分享:
扫描分享到社交APP
上一篇
下一篇