下面我将分别详细介绍 Calendar 和 java.time 的用法,并提供一个对比总结。

使用 java.util.Calendar (传统方式)
Calendar 是一个抽象类,它不能直接实例化,通常使用 Calendar.getInstance() 方法来获取一个代表当前时间的 Calendar 对象。
1 获取当前时间
import java.util.Calendar;
public class CalendarExample {
public static void main(String[] args) {
// 1. 获取一个代表当前日期和时间的 Calendar 实例
Calendar now = Calendar.getInstance();
// 2. 获取年、月、日、时、分、秒等
int year = now.get(Calendar.YEAR);
// 月份是从 0 开始的,0 代表一月,11 代表十二月
int month = now.get(Calendar.MONTH) + 1;
int day = now.get(Calendar.DAY_OF_MONTH);
int hour = now.get(Calendar.HOUR_OF_DAY); // 24小时制
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);
System.out.println("使用 java.util.Calendar 获取当前时间:");
System.out.printf("年: %d, 月: %d, 日: %d, 时: %d, 分: %d, 秒: %d%n",
year, month, day, hour, minute, second);
}
}
重要提示:
Calendar.MONTH的索引是从 0 开始的。Calendar.JANUARY的值是 0,Calendar.DECEMBER的值是 11,所以在获取月份时,通常需要+ 1。
2 设置时间
你可以使用 set() 方法来修改 Calendar 对象中的时间字段。
import java.util.Calendar;
public class CalendarSetExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 设置日期为 2025年10月26日
calendar.set(2025, Calendar.OCTOBER, 26);
System.out.println("设置后的日期: " + calendar.getTime());
// 设置时间为 15点30分
calendar.set(Calendar.HOUR_OF_DAY, 15);
calendar.set(Calendar.MINUTE, 30);
System.out.println("设置后的时间: " + calendar.getTime());
}
}
3 时间计算(加减)
Calendar 提供了 add() 和 roll() 方法来进行时间的加减。

add(field, amount): 指定字段的值增加或减少amount,同时会影响到更大的字段(增加月份会自动调整年份)。roll(field, amount): 只改变指定字段的值,不会影响更大的字段(月份从12增加到1,年份不会改变)。
import java.util.Calendar;
public class CalendarAddExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
System.out.println("当前时间: " + calendar.getTime());
// 当前时间加10天
calendar.add(Calendar.DAY_OF_MONTH, 10);
System.out.println("10天后: " + calendar.getTime());
// 重置回当前时间
calendar = Calendar.getInstance();
// 当前时间减3个月
calendar.add(Calendar.MONTH, -3);
System.out.println("3个月后: " + calendar.getTime());
}
}
4 获取特定时间点
import java.util.Calendar;
public class CalendarGetTimeExample {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 获取该月的第一天
calendar.set(Calendar.DAY_OF_MONTH, 1);
System.out.println("这个月的第一天是: " + calendar.getTime());
// 获取该年的最后一天
calendar.set(Calendar.MONTH, Calendar.DECEMBER);
calendar.set(Calendar.DAY_OF_MONTH, 31);
System.out.println("今年的最后一天是: " + calendar.getTime());
}
}
使用 java.time (推荐方式,Java 8+)
java.time 是 Java 8 引入的新日期时间 API,它解决了 java.util.Date 和 Calendar 的诸多问题,如线程安全、API 设计清晰等。
1 核心类
LocalDate: 表示一个日期(年、月、日),不包含时间。LocalTime: 表示一个时间(时、分、秒、纳秒),不包含日期。LocalDateTime: 表示一个日期和时间(年、月、日、时、分、秒、纳秒)。ZonedDateTime: 表示一个带时区的日期和时间。Instant: 表示一个时间戳,与System.currentTimeMillis()类似,但更精确。
2 获取当前时间
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class JavaTimeExample {
public static void main(String[] args) {
// 1. 获取当前日期 (LocalDate)
LocalDate today = LocalDate.now();
System.out.println("当前日期: " + today); // 格式: 2025-10-26
// 2. 获取当前时间 (LocalTime)
LocalTime now = LocalTime.now();
System.out.println("当前时间: " + now); // 格式: 14:30:45.123
// 3. 获取当前日期和时间 (LocalDateTime)
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("当前日期和时间: " + nowDateTime); // 格式: 2025-10-26T14:30:45.123
// 4. 获取带时区的当前日期和时间 (ZonedDateTime)
ZonedDateTime nowWithZone = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println("上海当前时间: " + nowWithZone);
}
}
3 设置时间和时间计算
java.time 使用不可变对象(Immutable Object),所有修改操作都会返回一个新的对象,而不是修改原对象。
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class JavaTimeManipulationExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间: " + now);
// 加10天
LocalDateTime plus10Days = now.plusDays(10);
System.out.println("10天后: " + plus10Days);
// 减3个月
LocalDateTime minus3Months = now.minusMonths(3);
System.out.println("3个月后: " + minus3Months);
// 加2小时30分钟
LocalDateTime plus2Hours30Minutes = now.plusHours(2).plusMinutes(30);
System.out.println("2小时30分钟后: " + plus2Hours30Minutes);
// 使用 ChronoUnit 进行更灵活的计算
LocalDateTime plus1YearAnd2Weeks = now.plus(1, ChronoUnit.YEARS).plus(2, ChronoUnit.WEEKS);
System.out.println("1年2周后: " + plus1YearAnd2Weeks);
}
}
4 格式化和解析
java.time 提供了 DateTimeFormatter 来轻松地格式化和解析日期时间。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class JavaTimeFormatExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
// 1. 格式化输出
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String formattedDateTime = now.format(formatter);
System.out.println("格式化后的时间: " + formattedDateTime); // 输出: 2025年10月26日 14:30:45
// 2. 解析字符串
String dateTimeString = "2025-02-28 20:00";
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, inputFormatter);
System.out.println("解析后的时间: " + parsedDateTime);
}
}
Calendar 与 java.time 对比总结
| 特性 | java.util.Calendar |
java.time (Java 8+) |
|---|---|---|
| API 设计 | API 不直观,方法名如 get() 和 add() 含义模糊。 |
API 非常清晰、流畅,方法名如 plusDays(), minusHours() 等。 |
| 可变性 | 可变 的,在多线程环境下不安全,需要额外同步。 | 不可变 的,线程安全,设计更优。 |
| 月份 | 从 0 开始 (0=一月),容易出错。 | 从 1 开始 (1=一月),符合直觉。 |
| 类型 | 一个类 (Calendar) 处理所有日期和时间。 |
使用多个类 (LocalDate, LocalTime, LocalDateTime 等) 职责分离。 |
| 现代特性 | 不支持时区操作等现代功能。 | 完美支持时区 (ZonedDateTime)、持续时间段 (Duration) 等。 |
| 易用性 | 格式化需要 SimpleDateFormat,本身线程不安全。 |
内置强大的 DateTimeFormatter,线程安全。 |
| 推荐度 | 不推荐,除非维护旧代码。 | 强烈推荐,所有新项目应使用此 API。 |
对于任何新的 Java 项目(使用 Java 8 或更高版本),请务必使用 java.time 包,它的设计更符合现代编程思想,API 更友好,能帮助你写出更健壮、更易维护的代码。
java.util.Calendar 只存在于需要维护旧项目(Java 7 或更早版本)的场景下。
