ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java 8 LocalDateTime类详解与实战应用

Java 8 LocalDateTime类详解与实战应用 1. LocalDateTime类概述LocalDateTime是Java 8中引入的一个不可变日期时间对象它表示没有时区的日期时间通常被视为年-月-日-小时-分钟-秒的组合。作为java.time包的核心类之一它完美替代了旧版的java.util.Date和java.util.Calendar提供了更直观、更安全的API设计。在实际开发中LocalDateTime特别适合以下场景需要同时处理日期和时间但不关心时区的业务逻辑生日、纪念日等不需要时区概念的日期时间记录与数据库交互时存储本地时间如MySQL的DATETIME类型2. 核心方法详解2.1 对象创建方法2.1.1 now()系列方法// 获取当前系统默认时区的日期时间 LocalDateTime now LocalDateTime.now(); // 获取指定时区的当前日期时间 LocalDateTime nowInTokyo LocalDateTime.now(ZoneId.of(Asia/Tokyo)); // 使用自定义时钟常用于测试 Clock testClock Clock.fixed(Instant.parse(2023-01-01T00:00:00Z), ZoneId.systemDefault()); LocalDateTime testTime LocalDateTime.now(testClock);注意在生产环境中使用now()时要注意时钟回拨问题。对于高精度时间要求场景建议使用NTP服务同步服务器时间。2.1.2 of()系列方法// 指定年月日时分创建秒和纳秒默认为0 LocalDateTime dt1 LocalDateTime.of(2023, Month.JANUARY, 15, 14, 30); // 指定年月日时分秒创建纳秒默认为0 LocalDateTime dt2 LocalDateTime.of(2023, 1, 15, 14, 30, 45); // 组合LocalDate和LocalTime创建 LocalDate date LocalDate.of(2023, 1, 15); LocalTime time LocalTime.of(14, 30); LocalDateTime dt3 LocalDateTime.of(date, time);2.2 时间获取与计算2.2.1 获取时间分量LocalDateTime dt LocalDateTime.now(); int year dt.getYear(); // 2023 Month month dt.getMonth(); // JANUARY int day dt.getDayOfMonth(); // 15 DayOfWeek dow dt.getDayOfWeek();// MONDAY int hour dt.getHour(); // 14 int minute dt.getMinute(); // 30 int second dt.getSecond(); // 45 int nano dt.getNano(); // 1234567892.2.2 时间加减计算LocalDateTime dt LocalDateTime.of(2023, 1, 15, 14, 30); // 加操作 LocalDateTime nextWeek dt.plusWeeks(1); LocalDateTime nextHour dt.plusHours(1); // 减操作 LocalDateTime lastMonth dt.minusMonths(1); LocalDateTime yesterday dt.minusDays(1); // 链式调用 LocalDateTime complex dt.plusDays(1).minusHours(3).plusMinutes(30);实战经验处理月末日期加减时要特别注意。例如1月31日加1个月会得到2月28日或29日而不是不存在的2月31日。2.3 时间调整与转换2.3.1 with()方法调整LocalDateTime dt LocalDateTime.of(2023, 1, 15, 14, 30); // 直接调整字段 LocalDateTime newYear dt.withYear(2024); LocalDateTime midnight dt.withHour(0).withMinute(0); // 使用TemporalAdjusters LocalDateTime lastDayOfMonth dt.with(TemporalAdjusters.lastDayOfMonth()); LocalDateTime nextMonday dt.with(TemporalAdjusters.next(DayOfWeek.MONDAY));2.3.2 时间截断LocalDateTime dt LocalDateTime.of(2023, 1, 15, 14, 30, 45, 123456789); // 截断到分钟 LocalDateTime truncatedToMinutes dt.truncatedTo(ChronoUnit.MINUTES); // 结果: 2023-01-15T14:30 // 截断到小时 LocalDateTime truncatedToHours dt.truncatedTo(ChronoUnit.HOURS); // 结果: 2023-01-15T14:003. 实用技巧与最佳实践3.1 日期时间格式化LocalDateTime dt LocalDateTime.now(); // 默认格式化为ISO格式 String isoFormat dt.toString(); // 2023-01-15T14:30:45.123 // 自定义格式化 DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); String customFormat dt.format(formatter); // 2023-01-15 14:30:45 // 解析字符串 LocalDateTime parsedDt LocalDateTime.parse(2023-01-15T14:30:45); LocalDateTime customParsed LocalDateTime.parse(2023-01-15 14:30, DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm));3.2 时间比较与间隔计算LocalDateTime dt1 LocalDateTime.of(2023, 1, 15, 14, 30); LocalDateTime dt2 LocalDateTime.of(2023, 1, 16, 10, 0); // 比较 boolean isBefore dt1.isBefore(dt2); // true boolean isAfter dt1.isAfter(dt2); // false // 计算时间间隔 Duration duration Duration.between(dt1, dt2); long hours duration.toHours(); // 19 long minutes duration.toMinutes(); // 1170 // 计算日期间隔忽略时间部分 Period period Period.between(dt1.toLocalDate(), dt2.toLocalDate()); int days period.getDays(); // 13.3 与旧API的互操作// 转换为java.util.Date LocalDateTime dt LocalDateTime.now(); Instant instant dt.atZone(ZoneId.systemDefault()).toInstant(); Date legacyDate Date.from(instant); // 从Date转换 Date date new Date(); LocalDateTime fromLegacy LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());4. 常见问题与解决方案4.1 时区处理误区虽然LocalDateTime不包含时区信息但在与Instant或ZonedDateTime转换时需要特别注意// 错误做法直接转换会丢失时区信息 LocalDateTime dt LocalDateTime.now(); Instant instant dt.toInstant(ZoneOffset.UTC); // 抛出异常 // 正确做法先指定时区再转换 Instant correctInstant dt.atZone(ZoneId.systemDefault()).toInstant();4.2 性能优化建议对于频繁使用的DateTimeFormatter应该缓存重用避免重复创建在循环中处理大量日期计算时考虑使用不可变对象链式调用序列化时优先使用ISO格式减少解析出错概率4.3 数据库交互技巧// JPA实体类中的使用示例 Entity public class Event { Column(name event_time) private LocalDateTime eventTime; // 使用AttributeConverter处理特殊格式 Convert(converter LocalDateTimeConverter.class) private LocalDateTime customFormatTime; } // 自定义转换器 Converter(autoApply true) public class LocalDateTimeConverter implements AttributeConverterLocalDateTime, String { private final DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy/MM/dd HH:mm); Override public String convertToDatabaseColumn(LocalDateTime attribute) { return attribute ! null ? attribute.format(formatter) : null; } Override public LocalDateTime convertToEntityAttribute(String dbData) { return dbData ! null ? LocalDateTime.parse(dbData, formatter) : null; } }5. 实际应用案例5.1 工作日计算public static LocalDateTime addWorkDays(LocalDateTime startDate, int workDays) { LocalDateTime result startDate; int addedDays 0; while (addedDays workDays) { result result.plusDays(1); if (result.getDayOfWeek() ! DayOfWeek.SATURDAY result.getDayOfWeek() ! DayOfWeek.SUNDAY) { addedDays; } } return result; }5.2 营业时间校验public boolean isWithinBusinessHours(LocalDateTime checkTime) { LocalTime time checkTime.toLocalTime(); DayOfWeek day checkTime.getDayOfWeek(); // 工作日9:00-18:00 if (day ! DayOfWeek.SATURDAY day ! DayOfWeek.SUNDAY) { return !time.isBefore(LocalTime.of(9, 0)) !time.isAfter(LocalTime.of(18, 0)); } // 周六9:00-12:00 else if (day DayOfWeek.SATURDAY) { return !time.isBefore(LocalTime.of(9, 0)) !time.isAfter(LocalTime.of(12, 0)); } // 周日休息 return false; }掌握LocalDateTime的各种用法可以显著提升Java日期时间处理的效率和准确性。在实际项目中建议结合具体业务场景选择合适的方法并注意处理好时区和异常边界情况。
返回列表