Java 中 LocalDateTime 的全面用法
1. 创建 LocalDateTime 实例
1.1 当前时间
// 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间: " + now); // 2026-01-21T10:30:15.123
// 获取当前时间(指定时区)
LocalDateTime nowInZone = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
1.2 指定时间创建
// 通过指定年月日时分秒
LocalDateTime dateTime1 = LocalDateTime.of(2024, 12, 25, 14, 30, 45);
LocalDateTime dateTime2 = LocalDateTime.of(2024, Month.DECEMBER, 25, 14, 30, 45);
// 通过 LocalDate 和 LocalTime 组合
LocalDate date = LocalDate.of(2024, 12, 25);
LocalTime time = LocalTime.of(14, 30, 45);
LocalDateTime dateTime3 = LocalDateTime.of(date, time);
1.3 解析字符串
// ISO 格式解析
LocalDateTime dt1 = LocalDateTime.parse("2024-12-25T14:30:45");
// 自定义格式解析
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime dt2 = LocalDateTime.parse("2024/12/25 14:30:45", formatter);
// 中文日期解析
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
LocalDateTime dt3 = LocalDateTime.parse("2024年12月25日 14时30分45秒", chineseFormatter);
2. 获取日期时间信息
LocalDateTime dt = LocalDateTime.now();
// 获取日期部分
int year = dt.getYear(); // 年
Month month = dt.getMonth(); // 月份枚举
int monthValue = dt.getMonthValue(); // 月份数值
int dayOfMonth = dt.getDayOfMonth(); // 当月第几天
int dayOfYear = dt.getDayOfYear(); // 当年第几天
DayOfWeek dayOfWeek = dt.getDayOfWeek(); // 星期几枚举
int dayOfWeekValue = dt.getDayOfWeek().getValue(); // 星期几数值(1=周一)
// 获取时间部分
int hour = dt.getHour(); // 时
int minute = dt.getMinute(); // 分
int second = dt.getSecond(); // 秒
int nano = dt.getNano(); // 纳秒
3. 日期时间计算
3.1 加减操作
LocalDateTime dt = LocalDateTime.now();
// 加法
LocalDateTime plusYears = dt.plusYears(1); // 加1年
LocalDateTime plusMonths = dt.plusMonths(2); // 加2月
LocalDateTime plusWeeks = dt.plusWeeks(3); // 加3周
LocalDateTime plusDays = dt.plusDays(7); // 加7天
LocalDateTime plusHours = dt.plusHours(3); // 加3小时
LocalDateTime plusMinutes = dt.plusMinutes(30); // 加30分钟
LocalDateTime plusSeconds = dt.plusSeconds(45); // 加45秒
// 减法
LocalDateTime minusYears = dt.minusYears(1); // 减1年
LocalDateTime minusHours = dt.minusHours(2); // 减2小时
// 链式调用
LocalDateTime result = dt.plusDays(7).minusHours(3);
3.2 使用 TemporalAmount
LocalDateTime dt = LocalDateTime.now();
// 使用 Period(日期部分)
Period oneMonth = Period.ofMonths(1);
LocalDateTime nextMonth = dt.plus(oneMonth);
// 使用 Duration(时间部分)
Duration twoHours = Duration.ofHours(2);
LocalDateTime later = dt.plus(twoHours);
// 组合使用
LocalDateTime combined = dt.plus(oneMonth).plus(twoHours);
4. 日期时间比较
LocalDateTime dt1 = LocalDateTime.parse("2024-12-25T14:30:00");
LocalDateTime dt2 = LocalDateTime.parse("2024-12-26T10:00:00");
// 比较
boolean isBefore = dt1.isBefore(dt2); // true
boolean isAfter = dt1.isAfter(dt2); // false
boolean isEqual = dt1.isEqual(dt2); // false
// 获取时间差
Duration duration = Duration.between(dt1, dt2);
long hours = duration.toHours(); // 19小时
long minutes = duration.toMinutes(); // 1170分钟
// 比较日期部分
boolean sameDay = dt1.toLocalDate().isEqual(dt2.toLocalDate()); // false
5. 格式化输出
LocalDateTime dt = LocalDateTime.now();
// 默认格式
String defaultFormat = dt.toString(); // 2024-12-25T14:30:45.123
// 自定义格式
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format1 = dt.format(formatter1); // 2024-12-25 14:30:45
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String format2 = dt.format(formatter2); // 2024年12月25日 14时30分45秒
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("EEE, MMM dd, yyyy hh:mm a", Locale.US);
String format3 = dt.format(formatter3); // Wed, Dec 25, 2024 02:30 PM
// 预定义格式
String isoFormat = dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
6. 与其它类型转换
6.1 与字符串互转
// LocalDateTime -> String
LocalDateTime dt = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
String str = dt.format(formatter);
// String -> LocalDateTime
LocalDateTime parsed = LocalDateTime.parse(str, formatter);
6.2 与 Date 互转
// LocalDateTime -> Date
LocalDateTime ldt = LocalDateTime.now();
Date date = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
// Date -> LocalDateTime
Date oldDate = new Date();
LocalDateTime newLdt = oldDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
6.3 与 Timestamp 互转
// LocalDateTime -> Timestamp
LocalDateTime ldt = LocalDateTime.now();
Timestamp timestamp = Timestamp.valueOf(ldt);
// Timestamp -> LocalDateTime
LocalDateTime fromTimestamp = timestamp.toLocalDateTime();
6.4 与 LocalDate/LocalTime 转换
LocalDateTime dt = LocalDateTime.now();
// 拆分为日期和时间
LocalDate date = dt.toLocalDate(); // 只获取日期部分
LocalTime time = dt.toLocalTime(); // 只获取时间部分
// 重新组合
LocalDateTime newDateTime = LocalDateTime.of(date, time);
7. 实际应用场景
7.1 验证日期
// 判断是否是特定日期
public boolean isChristmas(LocalDateTime dateTime) {
return dateTime.getMonth() == Month.DECEMBER && dateTime.getDayOfMonth() == 25;
}
// 判断是否在工作时间内
public boolean isWorkingHours(LocalDateTime dateTime) {
LocalTime time = dateTime.toLocalTime();
return time.isAfter(LocalTime.of(9, 0))
&& time.isBefore(LocalTime.of(18, 0))
&& dateTime.getDayOfWeek().getValue() <= 5; // 周一到周五
}
7.2 计算时间差
public String getTimeAgo(LocalDateTime pastTime) {
Duration duration = Duration.between(pastTime, LocalDateTime.now());
if (duration.toMinutes() < 1) {
return "刚刚";
} else if (duration.toHours() < 1) {
return duration.toMinutes() + "分钟前";
} else if (duration.toDays() < 1) {
return duration.toHours() + "小时前";
} else {
return duration.toDays() + "天前";
}
}
7.3 定时任务示例
// 计算下次执行时间
public LocalDateTime calculateNextExecution(LocalDateTime lastExecution, Duration interval) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextExecution = lastExecution.plus(interval);
// 如果下次执行时间已过,找到下一个可执行时间
while (nextExecution.isBefore(now)) {
nextExecution = nextExecution.plus(interval);
}
return nextExecution;
}
8. 数据库操作(JPA/Hibernate)
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String orderNo;
// 直接映射
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
// 自动设置创建和更新时间
@PrePersist
protected void onCreate() {
createTime = LocalDateTime.now();
updateTime = createTime;
}
@PreUpdate
protected void onUpdate() {
updateTime = LocalDateTime.now();
}
// 业务方法:计算过期时间
public LocalDateTime getExpireTime() {
return createTime.plusDays(30); // 30天后过期
}
// 判断是否过期
public boolean isExpired() {
return LocalDateTime.now().isAfter(getExpireTime());
}
}
9. 实用工具类示例
public class DateTimeUtils {
// 获取当天开始时间
public static LocalDateTime getStartOfDay(LocalDateTime dateTime) {
return dateTime.toLocalDate().atStartOfDay();
}
// 获取当天结束时间
public static LocalDateTime getEndOfDay(LocalDateTime dateTime) {
return dateTime.toLocalDate().atTime(LocalTime.MAX);
}
// 获取本周第一天
public static LocalDateTime getStartOfWeek(LocalDateTime dateTime) {
return dateTime.minusDays(dateTime.getDayOfWeek().getValue() - 1)
.toLocalDate()
.atStartOfDay();
}
// 获取本月第一天
public static LocalDateTime getStartOfMonth(LocalDateTime dateTime) {
return dateTime.withDayOfMonth(1)
.toLocalDate()
.atStartOfDay();
}
// 格式化显示
public static String formatDateTime(LocalDateTime dateTime, String pattern) {
if (dateTime == null) return "";
return dateTime.format(DateTimeFormatter.ofPattern(pattern));
}
// 判断两个时间是否在同一周
public static boolean isSameWeek(LocalDateTime dt1, LocalDateTime dt2) {
LocalDateTime startOfWeek1 = getStartOfWeek(dt1);
LocalDateTime startOfWeek2 = getStartOfWeek(dt2);
return startOfWeek1.isEqual(startOfWeek2);
}
}
10. 常见注意事项
// 1. 不可变性(每次操作都返回新对象)
LocalDateTime original = LocalDateTime.now();
LocalDateTime modified = original.plusDays(1);
System.out.println(original == modified); // false
// 2. 时区处理
LocalDateTime localDateTime = LocalDateTime.now(); // 不带时区
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai")); // 带时区
// 3. 空值处理
public void processDateTime(@Nullable LocalDateTime dateTime) {
if (dateTime == null) {
dateTime = LocalDateTime.now(); // 设置默认值
}
// 处理逻辑
}
// 4. 序列化(配合 Jackson)
// 在配置文件中添加:
// spring.jackson.serialization.write-dates-as-timestamps=false
// spring.jackson.time-zone=Asia/Shanghai
总结
- LocalDateTime 是不可变和线程安全的
- 所有修改操作都返回新对象
- 非常适合表示不含时区的本地日期时间
- 与 MySQL 的 datetime 类型完美对应
- 建议新项目全部使用 java.time 包