2026/1/21 3:39:45
网站建设
项目流程
爱站网注册人查询,手机微网站注册登录源码,一般通过什么确定险情的严重程度,云主机下载一、Java 8 之前的日期时间 API 问题1. 设计缺陷Date 类#xff1a;既包含日期又包含时间#xff0c;且时间以毫秒数存储#xff0c;设计混乱#xff0c;Date可变#xff0c;线程不安全Calendar 类#xff1a;月份从0开始#xff08;0一月#xff09;#xff0c;不符合…一、Java 8 之前的日期时间 API 问题1.设计缺陷Date 类既包含日期又包含时间且时间以毫秒数存储设计混乱Date可变线程不安全Calendar 类月份从0开始0一月不符合人类直觉反人类设计SimpleDateFormat 非线程安全多线程环境下需要额外同步2.代码示例 - 旧API的坑❌ 月份从0开始年份要减1900❌ Date可变线程不安全❌ SimpleDateFormat线程不安全❌ API设计混乱❌ 时区处理复杂// 1. 月份从0开始 Date date new Date(2025-1900, 0, 1); // 2025年1月1日实际上是2025年1月1日 // 实际上月份参数0表示一月 // 2. SimpleDateFormat 线程不安全 SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd); // 多线程使用会抛出异常 // 3. 日期计算复杂 Calendar calendar Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, 5); // 增加5天 // 代码冗长可读性差 // 4. 时区处理混乱 Date date new Date(); // 默认使用系统时区转换麻烦 Date now newDate(); now.setTime(0); // 可以随意修改多线程下危险二、Java 8 日期时间 API 核心类1.主要类层次结构java.time ├── LocalDate // 日期年-月-日 ├── LocalTime // 时间时-分-秒-纳秒 ├── LocalDateTime // 日期时间 ├── ZonedDateTime // 带时区的日期时间 ├── Instant // 时间戳Unix时间 ├── Duration // 时间间隔秒纳秒 ├── Period // 日期间隔年月日 └── DateTimeFormatter // 格式化器2.Java 8新API的优势 ✨// 新API简洁、清晰、不可变 LocalDate date LocalDate.of(2025, 1, 15); // 就是2025年1月15日 LocalDate tomorrow date.plusDays(1); // 返回新对象原对象不变 // 线程安全的格式化 DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd); Stringstr date.format(formatter); // 完全线程安全 // 流畅的API LocalDateTime now LocalDateTime.now() .plusDays(7) .minusHours(2) .withMinute(30);三、核心类详解1.LocalDate - 本地日期// 创建 LocalDate today LocalDate.now(); LocalDate specificDate LocalDate.of(2025, 12, 25); LocalDate parsedDate LocalDate.parse(2025-12-25); // 操作 LocalDate tomorrow today.plusDays(1); LocalDate nextMonth today.plusMonths(1); LocalDate previousYear today.minusYears(1); // 获取信息 int year today.getYear(); Month month today.getMonth(); // 返回Month枚举 int dayOfMonth today.getDayOfMonth(); DayOfWeek dayOfWeek today.getDayOfWeek(); // 判断 boolean isLeapYear today.isLeapYear(); boolean isBefore today.isBefore(LocalDate.of(2025, 1, 1));2.LocalTime - 本地时间// 创建 LocalTime now LocalTime.now(); LocalTime specificTime LocalTime.of(14, 30, 45); // 14:30:45 LocalTime parsedTime LocalTime.parse(14:30:45); // 操作 LocalTime plusHours now.plusHours(2); LocalTime minusMinutes now.minusMinutes(30); // 获取信息 int hour now.getHour(); int minute now.getMinute(); int second now.getSecond();3.LocalDateTime - 本地日期时间// 创建 LocalDateTime now LocalDateTime.now(); LocalDateTime specificDateTime LocalDateTime.of(2025, 12, 25, 14, 30); LocalDateTime combined LocalDateTime.of(today, now); // 转换 LocalDate date now.toLocalDate(); LocalTime time now.toLocalTime(); // 操作 LocalDateTime nextWeek now.plusWeeks(1); LocalDateTime lastHour now.minusHours(1);4.Instant - 时间戳// 创建 Instant now Instant.now(); Instant specific Instant.ofEpochSecond(1700000000L); // 转换 Instant fromDate date.atStartOfDay(ZoneId.systemDefault()).toInstant(); LocalDateTime ldt LocalDateTime.ofInstant(now, ZoneId.systemDefault()); // 计算 Instant plusSeconds now.plusSeconds(3600); Duration between Duration.between(now, plusSeconds);5.ZonedDateTime - 带时区日期时间// 创建 ZonedDateTime nowInShanghai ZonedDateTime.now(ZoneId.of(Asia/Shanghai)); ZonedDateTime zoned ZonedDateTime.of( LocalDateTime.now(), ZoneId.of(America/New_York) ); // 时区转换 ZonedDateTime nowTime ZonedDateTime.now(ZoneId.of(Asia/Shanghai)); ZonedDateTime newYorkTime nowTime.withZoneSameInstant( ZoneId.of(America/New_York) ); // 获取所有可用时区 SetString allZones ZoneId.getAvailableZoneIds();6.Duration 和 Period// Duration - 时间间隔精确到纳秒 Duration duration Duration.between( LocalTime.of(14, 0), LocalTime.of(16, 30) ); long hours duration.toHours(); // 2 long minutes duration.toMinutes(); // 150 // Period - 日期间隔年、月、日 Period period Period.between( LocalDate.of(2025, 1, 1), LocalDate.of(2025, 12, 31) ); int months period.getMonths(); // 11 int days period.getDays(); // 30四、格式化与解析1.DateTimeFormatter// 预定义格式器 LocalDateTime now LocalDateTime.now(); String isoFormat now.format(DateTimeFormatter.ISO_DATE_TIME); // 自定义格式 DateTimeFormatter formatter DateTimeFormatter .ofPattern(yyyy-MM-dd HH:mm:ss) .withLocale(Locale.CHINA); // 格式化 String formatted now.format(formatter); // 解析 LocalDateTime parsed LocalDateTime.parse(2025-12-25 14:30:00, formatter); // 本地化格式 DateTimeFormatter germanFormatter DateTimeFormatter .ofLocalizedDateTime(FormatStyle.MEDIUM) .withLocale(Locale.GERMAN);五、实用操作示例1.日期计算// 计算两个日期之间的天数 long daysBetween ChronoUnit.DAYS.between( LocalDate.of(2025, 1, 1), LocalDate.of(2025, 12, 31) ); // 获取本月第一天和最后一天 LocalDate firstDay today.with(TemporalAdjusters.firstDayOfMonth()); LocalDate lastDay today.with(TemporalAdjusters.lastDayOfMonth()); // 获取下个周一 LocalDate nextMonday today.with(TemporalAdjusters.next(DayOfWeek.MONDAY));2.时区处理// 获取当前所有时区的当前时间 MapString, LocalDateTime timesInAllZones ZoneId.getAvailableZoneIds().stream() .collect(Collectors.toMap( zone - zone, zone - LocalDateTime.now(ZoneId.of(zone)) )); // 判断是否夏令时 ZoneId zone ZoneId.of(Asia/Shanghai); ZonedDateTime zdt ZonedDateTime.now(zone); boolean isDST zdt.getZone().getRules().isDaylightSavings(zdt.toInstant());3.业务常见场景// 1. 计算年龄 public int calculateAge(LocalDate birthDate) { return Period.between(birthDate, LocalDate.now()).getYears(); } // 2. 计算工作日排除周末 public long calculateWorkingDays(LocalDate start, LocalDate end) { return Stream.iterate(start, date - date.plusDays(1)) .limit(ChronoUnit.DAYS.between(start, end)) .filter(date - date.getDayOfWeek() ! DayOfWeek.SATURDAY date.getDayOfWeek() ! DayOfWeek.SUNDAY) .count(); } // 3. 定时任务执行时间计算 public LocalDateTime nextExecutionTime(LocalDateTime lastExecution, Duration interval) { return lastExecution.plus(interval); }六、与传统API的互操作// Date 转 LocalDateTime Date oldDate new Date(); LocalDateTime newDateTime oldDate.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDateTime(); // LocalDateTime 转 Date LocalDateTime ldt LocalDateTime.now(); Date date Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()); // Calendar 转 LocalDate Calendar calendar Calendar.getInstance(); LocalDate localDate LocalDate.of( calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) 1, // 注意月份1 calendar.get(Calendar.DAY_OF_MONTH) );七、最佳实践1.选择正确的类只关心日期 →LocalDate只关心时间 →LocalTime需要日期时间 →LocalDateTime需要时区 →ZonedDateTime时间戳存储 →Instant2.线程安全// DateTimeFormatter 是线程安全的可以共享 private static final DateTimeFormatter FORMATTER DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); public String formatDateTime(LocalDateTime dateTime) { return dateTime.format(FORMATTER); // 线程安全 }3.避免空指针public OptionalLocalDate parseDate(String dateStr) { try { return Optional.of(LocalDate.parse(dateStr)); } catch (DateTimeParseException e) { return Optional.empty(); } }八、总结对比特性旧API (java.util.Date)新API (java.time)设计清晰度混乱一锅炖职责单一清晰线程安全不安全所有类不可变线程安全月份表示0-110一月1-12符合直觉格式化SimpleDateFormat非线程安全DateTimeFormatter线程安全时区处理复杂易错内置支持完善日期计算繁琐简单直观可读性差优秀Java 8 日期时间 API 的设计遵循了以下原则不可变性所有核心类都是不可变的清晰性类名和方法名明确表达意图流畅性方法链式调用代码流畅扩展性支持自定义的时间调节器完整性覆盖了所有常见的日期时间操作场景建议所有新项目都使用 Java 8 日期时间 API对于老项目逐步迁移替换。