java.util.Calendar 是 Java 8 之前用于处理日期和时间的核心类,虽然现在官方推荐使用 java.time 包(Java 8+ 引入),但 Calendar 仍然在许多遗留代码中广泛使用,因此理解它非常重要。

获取当前小时
Calendar 使用不同的常量来表示不同的时间字段,获取小时需要使用 Calendar.HOUR 和 Calendar.HOUR_OF_DAY。
Calendar.HOUR (12小时制)
- 含义: 表示上午或下午的小时,范围是
0到11。 0代表 12 点(午夜 12 点或中午 12 点)。11代表 11 点(上午 11 点或晚上 11 点)。- 要区分上午还是下午,需要配合
Calendar.AM_PM字段。
Calendar.HOUR_OF_DAY (24小时制)
- 含义: 表示一天中的小时,范围是
0到23。 0代表午夜 0 点。23代表晚上 11 点。- 这是最常用、最不容易出错的方式。
代码示例:获取当前小时
import java.util.Calendar;
public class CalendarHourExample {
public static void main(String[] args) {
// 1. 获取一个 Calendar 实例,默认设置为当前日期和时间
Calendar now = Calendar.getInstance();
// 2. 获取 24 小时制的小时数 (0-23)
int hourOfDay = now.get(Calendar.HOUR_OF_DAY);
System.out.println("当前小时 (24小时制): " + hourOfDay);
// 3. 获取 12 小时制的小时数 (0-11)
int hour = now.get(Calendar.HOUR);
System.out.println("当前小时 (12小时制): " + hour);
// 4. 获取 AM/PM 标记 (0=AM, 1=PM)
int amPm = now.get(Calendar.AM_PM);
String amPmString = (amPm == Calendar.AM) ? "AM" : "PM";
System.out.println("上午/下午: " + amPmString);
// 综合显示 12 小时制时间
System.out.printf("综合 12 小时制时间: %d %s%n", hour, amPmString);
}
}
可能的输出:
当前小时 (24小时制): 14
当前小时 (12小时制): 2
上午/下午: PM
综合 12 小时制时间: 2 PM
设置小时
你可以使用 set() 方法来设置 Calendar 实例中的小时。
代码示例:设置小时
import java.util.Calendar;
public class CalendarSetHourExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 设置时间为 2025年10月27日 15:30:00
calendar.set(2025, Calendar.OCTOBER, 27, 15, 30, 0);
System.out.println("设置前的小时 (24小时制): " + calendar.get(Calendar.HOUR_OF_DAY)); // 输出 15
// --- 设置小时的操作 ---
// a) 设置 24 小时制的小时
calendar.set(Calendar.HOUR_OF_DAY, 22); // 设置为晚上 10 点
System.out.println("设置 24 小时制后的小时: " + calendar.get(Calendar.HOUR_OF_DAY)); // 输出 22
// b) 设置 12 小时制的小时
// 注意:这不会改变 AM/PM 的状态
calendar.set(Calendar.HOUR, 9); // 设置为 9 点 (上午或下午取决于当前 AM/PM)
System.out.println("设置 12 小时制后的小时: " + calendar.get(Calendar.HOUR)); // 输出 9
System.out.println("此时的小时 (24小时制): " + calendar.get(Calendar.HOUR_OF_DAY)); // 输出 22 (仍然是晚上)
// 如果想明确设置为上午 9 点,需要同时设置 AM/PM
calendar.set(Calendar.HOUR, 9);
calendar.set(Calendar.AM_PM, Calendar.AM);
System.out.println("设置为上午 9 点后的小时 (24小时制): " + calendar.get(Calendar.HOUR_OF_DAY)); // 输出 9
}
}
增加或减少小时
使用 add() 方法可以在某个时间字段上增加或减少一个值,这个方法会处理字段的进位和借位。

add(field, amount):amount为正,则增加;为负,则减少。
代码示例:增加/减少小时
import java.util.Calendar;
public class CalendarAddHourExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
System.out.println("当前时间: " + calendar.getTime());
// 增加小时
calendar.add(Calendar.HOUR_OF_DAY, 5); // 增加 5 个小时
System.out.println("增加 5 小时后: " + calendar.getTime());
// 减少小时
calendar.add(Calendar.HOUR_OF_DAY, -10); // 减少 10 个小时
System.out.println("减少 10 小时后: " + calendar.getTime());
// 示例:跨日计算
calendar.set(Calendar.HOUR_OF_DAY, 23); // 设置为晚上 11 点
System.out.println("设置为晚上 11 点: " + calendar.getTime());
calendar.add(Calendar.HOUR_OF_DAY, 2); // 再增加 2 小时
System.out.println("再增加 2 小时后 (会自动进位到下一天): " + calendar.getTime());
// 输出会是第二天的凌晨 1 点
}
}
重要提醒:java.util.Calendar 的问题
java.util.Calendar 设计上存在一些问题,这也是为什么 Java 8 引入了全新的 java.time API 的原因。
- 月份从 0 开始:
Calendar.JANUARY的值是0,而不是1,这是新手最容易犯的错误。 - 可变性:
Calendar对象是可变的,像add()和set()这样的方法会修改对象本身,而不是返回一个新的实例,这在并发环境下是不安全的,也使得代码难以维护。 - API 设计笨拙: 获取和设置时间的方式比较繁琐。
现代替代方案:java.time (Java 8+)
如果你使用的是 Java 8 或更高版本,强烈推荐使用 java.time 包,它的 API 更直观、更安全、更易用。
java.time.LocalTime 类
LocalTime 是一个专门用于表示“时间”(不含日期)的不可变类。
代码示例:使用 java.time.LocalTime
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
public class JavaTimeExample {
public static void main(String[] args) {
// 1. 获取当前时间
LocalTime now = LocalTime.now();
System.out.println("当前时间: " + now);
// 2. 获取小时 (24小时制)
int hour = now.getHour();
System.out.println("当前小时: " + hour);
// 3. 获取分钟和秒
int minute = now.getMinute();
int second = now.getSecond();
System.out.printf("分钟: %d, 秒: %d%n", minute, second);
// 4. 创建特定时间
LocalTime specificTime = LocalTime.of(15, 30, 45); // 15:30:45
System.out.println("特定时间: " + specificTime);
// 5. 增加或减少时间 (返回新的 LocalTime 实例,原对象不变)
LocalTime later = now.plusHours(2);
System.out.println("2 小时后: " + later);
LocalTime earlier = now.minusMinutes(30);
System.out.println("30 分钟前: " + earlier);
// 6. 计算时间差
long hoursBetween = ChronoUnit.HOURS.between(now, later);
System.out.println("时间差 (小时): " + hoursBetween);
}
}
| 特性 | java.util.Calendar |
java.time.LocalTime (推荐) |
|---|---|---|
| 获取小时 | calendar.get(Calendar.HOUR_OF_DAY) |
localTime.getHour() |
| 设置小时 | calendar.set(Calendar.HOUR_OF_DAY, 10) |
localTime.withHour(10) (返回新对象) |
| 增减小时 | calendar.add(Calendar.HOUR_OF_DAY, 1) |
localTime.plusHours(1) (返回新对象) |
| 可变性 | 可变 | 不可变 (线程安全) |
| API 设计 | 相对繁琐 | 简洁、直观 |
| 推荐度 | 仅用于维护旧代码 | 强烈推荐用于新项目 |
对于新的 Java 项目,请务必使用 java.time API,对于需要维护的旧代码,你需要理解 Calendar 的工作方式,特别是 HOUR_OF_DAY (24小时制) 的用法。

