Java Calendar 类

Calendar 类是 Java 中用于处理日期和时间的抽象类,它位于 java.util 包中。这个类提供了一系列方法来操作日期和时间字段(如年、月、日、小时、分钟等),并且可以执行日期计算和比较。

为什么需要 Calendar 类?

在 Java 中,虽然 Date 类也可以表示日期和时间,但它存在以下局限性:

  1. 大部分方法已经过时(deprecated)
  2. 不支持国际化
  3. 日期计算功能有限

Calendar 类解决了这些问题,提供了更强大、更灵活的日期时间操作功能。


Calendar 类的基本使用

获取 Calendar 实例

由于 Calendar 是抽象类,我们不能直接实例化它。获取 Calendar 实例的标准方法是:

实例

Calendar calendar = Calendar.getInstance();

这个方法会根据默认时区和地区返回一个 Calendar 实例(通常是 GregorianCalendar)。

设置日期和时间

我们可以使用 set() 方法来设置 Calendar 对象的各个字段:

实例

// 设置年月日
calendar.set(2023, Calendar.NOVEMBER, 15);

// 设置年月日时分秒
calendar.set(2023, Calendar.NOVEMBER, 15, 14, 30, 0);

注意:月份是从 0 开始的,0 表示一月,11 表示十二月。为了避免混淆,建议使用 Calendar 类中定义的常量(如 Calendar.JANUARY、Calendar.FEBRUARY 等)。

获取日期和时间信息

使用 get() 方法可以获取 Calendar 对象中的各个字段:

实例

int year = calendar.get(Calendar.YEAR);       // 获取年份
int month = calendar.get(Calendar.MONTH);     // 获取月份(0-11)
int day = calendar.get(Calendar.DAY_OF_MONTH);// 获取日
int hour = calendar.get(Calendar.HOUR_OF_DAY);// 获取小时(24小时制)
int minute = calendar.get(Calendar.MINUTE);   // 获取分钟
int second = calendar.get(Calendar.SECOND);   // 获取秒

Calendar 类的常用方法

日期计算

Calendar 类提供了方便的日期计算方法:

实例

// 在当前日期上加10天
calendar.add(Calendar.DAY_OF_MONTH, 10);

// 在当前月份上减3个月
calendar.add(Calendar.MONTH, -3);

日期比较

我们可以使用 compareTo() 方法比较两个 Calendar 对象:

实例

Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.DAY_OF_MONTH, 1);

int result = cal1.compareTo(cal2);
// result < 0 表示 cal1 早于 cal2
// result == 0 表示 cal1 等于 cal2
// result > 0 表示 cal1 晚于 cal2

获取时间戳

可以使用 getTimeInMillis() 方法获取 Calendar 对象表示的时间戳(毫秒数):

实例

long timestamp = calendar.getTimeInMillis();

也可以使用 getTime() 方法将其转换为 Date 对象:

实例

Date date = calendar.getTime();

Calendar 类的高级用法

设置时区

我们可以为 Calendar 对象设置特定的时区:

实例

TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
calendar.setTimeZone(timeZone);

日历字段操作

Calendar 类提供了 roll() 方法,可以在不影响其他字段的情况下滚动某个字段:

实例

// 将月份增加1,但不会改变年份
calendar.roll(Calendar.MONTH, true);  // 或 calendar.roll(Calendar.MONTH, 1);

获取一周的第一天

不同地区对一周的第一天定义不同(有些是周日,有些是周一):

实例

int firstDayOfWeek = calendar.getFirstDayOfWeek();

Calendar 类的注意事项

  1. 月份从0开始:Calendar 类中月份是从0开始的(0=一月,11=十二月),这容易导致错误。

  2. 可变性:Calendar 对象是可变的,修改一个 Calendar 对象会影响所有引用它的地方。

  3. 线程安全:Calendar 类不是线程安全的,多线程环境下需要额外同步。

  4. 性能:频繁创建 Calendar 实例会影响性能,可以考虑重用实例。

  5. 时区问题:默认使用系统时区,跨时区应用需要特别注意。


Java 8 中的替代方案

从 Java 8 开始,引入了新的日期时间 API(java.time 包),提供了更现代、更易用的日期时间处理方式。如果使用 Java 8 或更高版本,建议优先使用新的 API:

实例

// 替代 Calendar 的新 API
LocalDate date = LocalDate.now();
LocalDateTime dateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.now();

新的 API 解决了 Calendar 类的许多问题,包括更好的线程安全性、更直观的 API 设计和更强大的功能。


Java Calendar 类常用方法

以下是 java.util.Calendar 类的常用方法:

基本方法

方法 描述 示例
static Calendar getInstance() 获取默认时区和语言环境的Calendar实例 Calendar cal = Calendar.getInstance()
static Calendar getInstance(TimeZone zone) 获取指定时区的Calendar实例 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"))
static Calendar getInstance(Locale locale) 获取指定语言环境的Calendar实例 Calendar cal = Calendar.getInstance(Locale.CHINA)
static Calendar getInstance(TimeZone zone, Locale locale) 获取指定时区和语言环境的Calendar实例 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"), Locale.CHINA)

字段常量(常用)

字段 描述 值范围
Calendar.YEAR 年字段 -
Calendar.MONTH 月字段 0-11 (0表示1月)
Calendar.DATECalendar.DAY_OF_MONTH 月中的天数 1-31
Calendar.DAY_OF_WEEK 星期几 1-7 (1表示周日)
Calendar.HOUR 12小时制的小时 0-11
Calendar.HOUR_OF_DAY 24小时制的小时 0-23
Calendar.MINUTE 分钟 0-59
Calendar.SECOND 0-59
Calendar.MILLISECOND 毫秒 0-999
Calendar.AM_PM 上午或下午 0 (AM) 或 1 (PM)

日期时间操作方法

方法 描述 示例
int get(int field) 获取指定字段的值 int year = cal.get(Calendar.YEAR)
void set(int field, int value) 设置指定字段的值 cal.set(Calendar.MONTH, 5) (设置为6月)
void set(int year, int month, int date) 设置年、月、日 cal.set(2023, 5, 15) (2023年6月15日)
void set(int year, int month, int date, int hourOfDay, int minute) 设置年、月、日、时、分 cal.set(2023, 5, 15, 14, 30)
void set(int year, int month, int date, int hourOfDay, int minute, int second) 设置年、月、日、时、分、秒 cal.set(2023, 5, 15, 14, 30, 45)
void add(int field, int amount) 添加或减去指定的时间量 cal.add(Calendar.DATE, 5) (加5天)
void roll(int field, int amount) 在不更改更大字段的情况下添加或减去时间量 cal.roll(Calendar.DATE, 5) (仅改变日字段)

时间比较方法

方法 描述 示例
boolean after(Object when) 判断此Calendar是否在指定时间之后 cal1.after(cal2)
boolean before(Object when) 判断此Calendar是否在指定时间之前 cal1.before(cal2)
int compareTo(Calendar anotherCalendar) 比较两个Calendar对象的时间顺序 cal1.compareTo(cal2)

其他实用方法

方法 描述 示例
long getTimeInMillis() 返回此Calendar的时间值(毫秒) long millis = cal.getTimeInMillis()
void setTimeInMillis(long millis) 用给定的毫秒时间值设置Calendar cal.setTimeInMillis(1626345600000L)
Date getTime() 返回表示此Calendar时间值的Date对象 Date date = cal.getTime()
void setTime(Date date) 使用给定的Date设置Calendar的时间 cal.setTime(new Date())
void clear() 清除所有字段值 cal.clear()
void clear(int field) 清除指定字段的值 cal.clear(Calendar.HOUR)
boolean isSet(int field) 判断指定字段是否已设置值 if(cal.isSet(Calendar.YEAR))