Java 8+ 时间类型 :从 LocalDateTime 到 Instant
一、核心前置知识1. 核心包所有新时间类型都位于java.time包下无需引入第三方依赖JDK 8 原生支持。2. 核心设计理念领域驱动设计将「日期、时间、时区、时间戳、时间间隔」严格拆分每个类型只负责一件事无歧义、无冗余。所有核心类都是✅不可变类修改时间会生成新对象线程安全✅语义清晰见名知意没有冗余方法✅时区安全区分「本地时间」和「全球时间」二、Java 8 常用时间类型全解我们按照业务场景将核心类型分为 4 大类逐一详解第一类无时区本地时间纯本地展示这类类型不包含任何时区信息仅表示「人类视角的本地日期 / 时间」比如生日、日程、本地闹钟不适合存储全球统一时间。表格类型含义格式示例核心特点LocalDate仅日期年月日2025-12-25无时间、无时区LocalTime仅时间时分秒纳秒20:30:59.999无日期、无时区LocalDateTime日期 时间2025-12-25T20:30:59无时区最常用本地类型import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; public class LocalTimeDemo { public static void main(String[] args) { // 1. 获取当前时间 LocalDate today LocalDate.now(); LocalTime nowTime LocalTime.now(); LocalDateTime now LocalDateTime.now(); // 2. 手动创建时间 LocalDate birthDay LocalDate.of(2000, 1, 1); LocalDateTime meeting LocalDateTime.of(2025, 12, 25, 14, 30); // 3. 常用操作加减时间不可变返回新对象 LocalDate nextWeek today.plusWeeks(1); LocalDateTime beforeHour now.minusHours(1); System.out.println(当前日期 today); System.out.println(会议时间 meeting); } }适用场景生日、纪念日、本地日程前端展示的纯本地时间与时区无关的业务场景第二类带时区 / 偏移量时间全球业务专用这类类型包含时区信息解决了「跨时区时间歧义」问题是跨境业务、分布式系统的首选。类型含义核心区别适用场景OffsetDateTime日期 时间 时区偏移量仅记录08:00这类偏移量轻量数据库存储、接口传输ZonedDateTime日期 时间 完整时区记录Asia/Shanghai支持夏令时时区转换、复杂时区业务关键区分OffsetDateTime固定偏移量无夏令时变化数据库官方推荐ZonedDateTime完整时区规则自动处理夏令时适合复杂时区计算import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; public class ZoneTimeDemo { public static void main(String[] args) { // 1. 当前带偏移量的时间 OffsetDateTime offsetNow OffsetDateTime.now(); // 2. 指定时区创建时间 ZonedDateTime shanghaiTime ZonedDateTime.now(ZoneId.of(Asia/Shanghai)); ZonedDateTime newYorkTime ZonedDateTime.now(ZoneId.of(America/New_York)); System.out.println(上海时间 shanghaiTime); System.out.println(纽约时间 newYorkTime); } }适用场景跨境电商、海外业务分布式系统的时间统一需要明确时区的业务逻辑第三类机器时间戳Instant是 Java 新时间 API 中最重要的类型专为计算机存储、计算设计。核心特性表示UTC 时区的时间戳从 1970-01-01 00:00:00 开始的秒 / 纳秒无任何时区歧义全球唯一不可变、线程安全、性能极高import java.time.Instant; public class InstantDemo { public static void main(String[] args) { // 1. 获取当前时间戳 Instant now Instant.now(); // 2. 时间戳转秒/毫秒兼容旧系统 long second now.getEpochSecond(); long milli now.toEpochMilli(); // 3. 手动创建 Instant instant Instant.ofEpochMilli(System.currentTimeMillis()); System.out.println(当前UTC时间 now); System.out.println(时间戳毫秒 milli); } }适用场景✅数据库存储时间的最佳选择✅ 日志时间、分布式锁超时、消息队列时间戳✅ 所有需要「全球统一、无歧义」的时间场景第四类时间间隔计算时间差专用专门用于计算两个时间的差值严格拆分「日期间隔」和「时间间隔」类型含义计算单位Period日期间隔年、月、日Duration时间间隔时、分、秒、纳秒import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Period; public class TimeGapDemo { public static void main(String[] args) { // 1. 计算日期间隔生日天数 LocalDate today LocalDate.now(); LocalDate birthDay LocalDate.of(2000, 1, 1); Period period Period.between(birthDay, today); System.out.println(年龄 period.getYears() 岁); // 2. 计算时间间隔会议时长 LocalDateTime start LocalDateTime.of(2025, 12, 25, 14, 0); LocalDateTime end LocalDateTime.of(2025, 12, 25, 16, 30); Duration duration Duration.between(start, end); System.out.println(会议时长 duration.toHours() 小时); } }三、高频实用操作格式化与转换1. 时间格式化 / 解析线程安全替代线程不安全的SimpleDateFormat使用DateTimeFormatterjava运行import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class FormatDemo { public static void main(String[] args) { // 定义格式化器 DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); LocalDateTime now LocalDateTime.now(); // 时间 → 字符串 String formatTime now.format(formatter); // 字符串 → 时间 LocalDateTime parseTime LocalDateTime.parse(2025-12-25 14:30:00, formatter); System.out.println(格式化后 formatTime); } }2. 核心类型转换// LocalDateTime → Instant带时区 LocalDateTime local LocalDateTime.now(); Instant instant local.atZone(ZoneId.systemDefault()).toInstant(); // Instant → LocalDateTime LocalDateTime localTime LocalDateTime.ofInstant(instant, ZoneId.systemDefault());四、开发避坑指南禁止用 LocalDateTime 存储全球时间无时区跨时区会出现时间错乱存储必须用Instant/OffsetDateTime。禁止使用 SimpleDateFormat线程不安全高并发下会出现格式化错误统一用DateTimeFormatter。Instant 是 UTC 时间直接打印会比北京时间晚 8 小时属于正常现象转换为本地时间即可。所有新时间类都是不可变的调用plus/minus方法必须接收返回值原对象不会改变。五、企业级最佳实践业务场景推荐类型理由数据库存储时间Instant/OffsetDateTime无歧义、跨时区兼容本地展示生日 / 日程LocalDateTime无时区语义清晰跨境 / 时区业务ZonedDateTime支持完整时区规则时间戳 / 日志 / 超时Instant机器时间性能最优计算日期差Period年月日间隔计算时间差Duration时分秒间隔六、总结Java 8java.time包的时间 API 是现代 Java 开发的标准工具彻底告别了传统时间类的痛点分工明确日期、时间、时区、时间戳各司其职线程安全所有类不可变高并发无压力无歧义解决了跨时区、时间格式化的所有坑易用性强API 语义清晰一行代码完成时间操作。核心存储用 Instant展示用 LocalDateTime时区用 ZonedDateTime计算用 Duration/Period。