Java 时间类(中):JDK8 全新时间 API 详细教程

Java 时间类(中):JDK8 全新时间 API 详细教程
在这里插入图片描述
🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言数据结构(C语言)EasyXJAVA游戏规划程序人生
✨ 从来绝巘须孤往,万里同尘即玉京
在这里插入图片描述


文章目录

在这里插入图片描述

Java 时间类(中):JDK8 全新时间 API 详细教程 🕘

线程安全、设计优雅、日常开发必用,建议和上篇 JDK7 时间类对照学习~

📝 文章摘要

  • 阅读时长:10 分钟
  • 适合人群
    1. 已经学完 JDK7 时间类,想升级 JDK8 写法的同学
    2. Java 初/中级开发者 → 重点看:LocalDateTime、DateTimeFormatter、时间计算
    3. 面试/工作党 → 重点看:不可变对象、线程安全、时间间隔工具
  • 本文内容:系统讲解 JDK8 全新时间类,包括时区、时间戳、日期时间、格式化、时间间隔,覆盖日常开发高频用法。

🧠 上篇知识回顾

  1. JDK7 时间类核心:Date(表示时间) + SimpleDateFormat(格式化解析) + Calendar(日历操作)
  2. 痛点:线程不安全、设计混乱(月份从 0 开始)、API 不够直观
  3. JDK8 新时间类优势:
    • 不可变对象,天然线程安全
    • 方法命名语义化,见名知意
    • 年月日常规从 1 开始,符合直觉
    • 按功能拆分(日期/时间/日期+时间),职责清晰

一、JDK8 时间类整体架构 🏛

JDK8 基于 ISO 8601 标准重构了时间 API,把时间功能拆解得清晰易懂:

类别核心类作用
时区ZoneId表示时区(如 Asia/Shanghai)
时间戳Instant表示 UTC 标准时间戳
带时区时间ZonedDateTime带时区的完整时间
纯日期LocalDate仅包含年月日
纯时间LocalTime仅包含时分秒纳秒
日期+时间LocalDateTime包含年月日时分秒
格式化解析DateTimeFormatter替代 SimpleDateFormat
时间间隔Period/Duration/ChronoUnit计算两个时间的间隔

二、ZoneId 时区类 🌍

1. 核心作用

表示全球各个时区,解决不同地区时间偏移的问题,是处理跨时区时间的基础。

2. 常用方法

方法名说明
ZoneId.systemDefault()获取系统默认时区
ZoneId.of(String zoneId)根据时区名获取指定时区
ZoneId.getAvailableZoneIds()获取 Java 支持的所有时区

3. 代码示例

importjava.time.ZoneId;importjava.util.Set;publicclassZoneIdDemo{publicstaticvoidmain(String[] args){// 1. 获取系统默认时区(国内通常是 Asia/Shanghai)ZoneId defaultZone =ZoneId.systemDefault();System.out.println("系统默认时区:"+ defaultZone);// 2. 获取指定时区ZoneId shanghaiZone =ZoneId.of("Asia/Shanghai");ZoneId tokyoZone =ZoneId.of("Asia/Tokyo");// 3. 查看所有支持的时区(约600个)Set<String> allZones =ZoneId.getAvailableZoneIds();System.out.println("Java支持的时区总数:"+ allZones.size());}}

三、Instant 时间戳类 ⚡

1. 核心作用

表示时间线上的一个瞬时点,对应 JDK7 的 Date 类,底层存储的是从 1970-01-01 00:00:00 UTC 开始的毫秒/纳秒数。

2. 常用方法

方法名说明
Instant.now()获取当前 UTC 时间戳
Instant.ofEpochMilli(long)根据毫秒值构建 Instant
Instant.ofEpochSecond(long)根据秒值构建 Instant
atZone(ZoneId zone)为时间戳绑定指定时区
isBefore(Instant other)判断当前时间是否在参数时间之前
isAfter(Instant other)判断当前时间是否在参数时间之后
plusSeconds(long) / minusSeconds(long)增加/减少指定秒数

3. 代码示例

importjava.time.Instant;importjava.time.ZoneId;importjava.time.ZonedDateTime;publicclassInstantDemo{publicstaticvoidmain(String[] args){// 1. 获取当前 UTC 时间戳Instant nowInstant =Instant.now();System.out.println("当前UTC时间戳:"+ nowInstant);// 2. 根据毫秒值构建(0毫秒对应1970-01-01 00:00:00 UTC)Instant zeroInstant =Instant.ofEpochMilli(0L);System.out.println("0毫秒对应的时间戳:"+ zeroInstant);// 3. 为时间戳绑定时区(转换为带时区的时间)ZonedDateTime shanghaiTime = nowInstant.atZone(ZoneId.of("Asia/Shanghai"));System.out.println("上海时区的当前时间:"+ shanghaiTime);// 4. 时间比较Instant oneSecond =Instant.ofEpochSecond(1L);boolean isBefore = zeroInstant.isBefore(oneSecond);// trueboolean isAfter = zeroInstant.isAfter(oneSecond);// falseSystem.out.println("0秒是否在1秒之前:"+ isBefore);// 5. 时间加减Instant addInstant = zeroInstant.plusSeconds(3600);// 加1小时System.out.println("加1小时后的时间:"+ addInstant);}}

四、ZonedDateTime 带时区时间 🕒

1. 核心特点

  • 包含完整的“日期+时间+时区”信息,是 Instant + ZoneId 的组合体
  • 不可变对象:修改时间会返回新的对象,原对象保持不变
  • 方法语义化,操作更直观

2. 常用方法

方法类型核心方法说明
获取对象ZonedDateTime.now()获取当前带时区时间
ZonedDateTime.of(年,月,日,时,分,秒,纳秒,时区)指定时间创建对象
ZonedDateTime.ofInstant(Instant, ZoneId)通过时间戳+时区创建
修改时间withYear(int) / withMonth(int)修改年/月(返回新对象)
增减时间plusYears(long) / minusMonths(long)增加/减少年/月(返回新对象)

3. 代码示例

importjava.time.Instant;importjava.time.ZoneId;importjava.time.ZonedDateTime;publicclassZonedDateTimeDemo{publicstaticvoidmain(String[] args){// 1. 获取当前带时区时间ZonedDateTime nowZoned =ZonedDateTime.now();System.out.println("当前带时区时间:"+ nowZoned);// 2. 指定时间创建ZonedDateTime customTime =ZonedDateTime.of(2026,10,1,// 年月日11,11,11,0,// 时分秒纳秒ZoneId.of("Asia/Shanghai")// 时区);System.out.println("指定的上海时间:"+ customTime);// 3. 通过Instant+时区创建Instant instant =Instant.ofEpochMilli(0L);ZonedDateTime zeroZoned =ZonedDateTime.ofInstant(instant,ZoneId.of("Asia/Shanghai"));System.out.println("0毫秒对应的上海时间:"+ zeroZoned);// 4. 修改时间(返回新对象,原对象不变)ZonedDateTime modifyYear = customTime.withYear(2025);ZonedDateTime minusMonth = modifyYear.minusMonths(1);System.out.println("修改并减1个月后的时间:"+ minusMonth);}}

五、DateTimeFormatter 格式化解析 ✨

1. 核心优势

替代 JDK7 的 SimpleDateFormat,解决了线程不安全的问题,是 JDK8 推荐的时间格式化工具。

2. 常用方法

方法名说明
DateTimeFormatter.ofPattern(String)根据指定格式创建格式化器
format(TemporalAccessor temporal)将时间对象格式化为字符串

3. 格式规则(与 SimpleDateFormat 一致)

常用格式模板:

  • yyyy-MM-dd:仅日期(如 2026-02-20)
  • HH:mm:ss:仅时间(如 15:30:45)
  • yyyy-MM-dd HH:mm:ss:日期+时间(如 2026-02-20 15:30:45)

4. 代码示例

importjava.time.ZonedDateTime;importjava.time.format.DateTimeFormatter;publicclassDateTimeFormatterDemo{publicstaticvoidmain(String[] args){// 1. 获取带时区的当前时间ZonedDateTime now =ZonedDateTime.now();// 2. 创建格式化器(指定格式)DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 3. 格式化时间(时间对象 → 字符串)String formatTime = formatter.format(now);System.out.println("格式化后的时间:"+ formatTime);}}

六、LocalDate / LocalTime / LocalDateTime 🌟

这三个类是 JDK8 时间 API 中日常开发使用频率最高的,按功能拆分,满足不同场景需求。

1. 功能分工

类名包含信息适用场景
LocalDate年、月、日生日、签到日期、订单日期
LocalTime时、分、秒、纳秒上下班打卡时间、活动开始时间
LocalDateTime年、月、日、时、分、秒日志记录、接口请求时间、数据创建时间

2. 通用核心方法

方法类型核心方法说明
获取对象XXX.now()获取当前时间/日期
XXX.of(...)指定时间/日期创建对象
获取字段getYear() / getMonthValue()获取年/月(月份1-12)
getDayOfMonth() / getHour()获取日/时
修改时间withYear(int) / withDayOfMonth(int)修改年/日
增减时间plusDays(long) / minusHours(long)增加/减少天/小时
时间比较isBefore(XXX) / isAfter(XXX)判断时间先后

3. LocalDate 代码示例(最常用)

importjava.time.LocalDate;importjava.time.DayOfWeek;publicclassLocalDateDemo{publicstaticvoidmain(String[] args){// 1. 获取当前日期LocalDate today =LocalDate.now();System.out.println("今天的日期:"+ today);// 2. 指定日期创建LocalDate customDate =LocalDate.of(2026,1,1);System.out.println("指定日期:"+ customDate);// 3. 获取日期字段int year = customDate.getYear();// 2026int month = customDate.getMonthValue();// 1(1-12,无需+1)int day = customDate.getDayOfMonth();// 1DayOfWeek week = customDate.getDayOfWeek();// 星期几System.out.println(year +"年"+ month +"月"+ day +"日 星期"+ week.getValue());// 4. 时间比较boolean isBefore = today.isBefore(customDate);System.out.println("今天是否在2026-01-01之前:"+ isBefore);// 5. 时间修改与增减LocalDate modifyDate = customDate.withYear(2025);// 修改年LocalDate addDate = modifyDate.plusMonths(3);// 加3个月System.out.println("修改并加3个月后的日期:"+ addDate);}}

4. 类之间的相互转换

LocalDateTime 可以拆分为 LocalDate 和 LocalTime:

importjava.time.LocalDateTime;publicclassLocalConvertDemo{publicstaticvoidmain(String[] args){LocalDateTime now =LocalDateTime.now();// LocalDateTime → LocalDateLocalDate date = now.toLocalDate();// LocalDateTime → LocalTimeLocalTime time = now.toLocalTime();System.out.println("拆分出的日期:"+ date);System.out.println("拆分出的时间:"+ time);}}

七、时间间隔计算:Period / Duration / ChronoUnit ⏳

日常开发中经常需要计算两个时间的间隔,JDK8 提供了三个工具类,满足不同粒度的需求。

1. Period —— 按“年、月、日”计算日期间隔

importjava.time.LocalDate;importjava.time.Period;publicclassPeriodDemo{publicstaticvoidmain(String[] args){// 起始日期LocalDate start =LocalDate.of(2020,1,1);// 结束日期LocalDate end =LocalDate.now();// 计算间隔Period period =Period.between(start, end);System.out.println("年差:"+ period.getYears());System.out.println("月差:"+ period.getMonths());System.out.println("日差:"+ period.getDays());System.out.println("总月数:"+ period.toTotalMonths());}}

2. Duration —— 按“时、分、秒、毫秒”计算时间间隔

importjava.time.LocalDateTime;importjava.time.Duration;publicclassDurationDemo{publicstaticvoidmain(String[] args){// 起始时间LocalDateTime start =LocalDateTime.of(2020,1,1,0,0);// 结束时间LocalDateTime end =LocalDateTime.now();// 计算间隔Duration duration =Duration.between(start, end);System.out.println("天差:"+ duration.toDays());System.out.println("小时差:"+ duration.toHours());System.out.println("分钟差:"+ duration.toMinutes());System.out.println("毫秒差:"+ duration.toMillis());}}

3. ChronoUnit —— 支持任意时间单位的间隔计算(最灵活)

importjava.time.LocalDateTime;importjava.time.temporal.ChronoUnit;publicclassChronoUnitDemo{publicstaticvoidmain(String[] args){// 起始时间LocalDateTime start =LocalDateTime.of(2007,8,13,14,0);// 结束时间LocalDateTime end =LocalDateTime.now();// 计算不同单位的间隔long years =ChronoUnit.YEARS.between(start, end);long months =ChronoUnit.MONTHS.between(start, end);long days =ChronoUnit.DAYS.between(start, end);long hours =ChronoUnit.HOURS.between(start, end);System.out.println("年差:"+ years);System.out.println("月差:"+ months);System.out.println("天差:"+ days);System.out.println("小时差:"+ hours);}}

📌 本篇知识回顾

  1. JDK8 时间类均为不可变对象,线程安全,修改/增减时间会返回新对象;
  2. 高频核心类:LocalDate(年月日)、LocalTime(时分秒)、LocalDateTime(年月日时分秒);
  3. 格式化工具:DateTimeFormatter 替代 SimpleDateFormat,解决线程安全问题;
  4. 时间间隔计算:Period(年月日)、Duration(时分秒)、ChronoUnit(任意单位)。

✍️ 写在最后

本篇我们系统学习了 JDK8 全新的时间 API,相比 JDK7 的传统时间类,它更优雅、更安全、更易用,是日常开发的首选。

下一篇我们将学习 Java 包装类相关知识:包括基本数据类型对应的包装类、自动装箱拆箱、常量池、字符串转基本类型等,这是 Java 基础的重要组成部分,也是面试高频考点!

如果你觉得本文对你有帮助,欢迎点赞 👍、收藏 💾、评论 💬,后续持续更新 Java 基础系列内容~

Read more

解锁超级生产力:手把手教你构建与GitHub深度集成的自动化工作流,让AI成为你的编程副驾驶

解锁超级生产力:手把手教你构建与GitHub深度集成的自动化工作流,让AI成为你的编程副驾驶

前言 在当今快节奏的软件开发世界中,效率就是生命线。每一位开发者、项目经理和技术爱好者都在不断寻求能够简化流程、自动化重复性任务并最终解放创造力的工具和方法。想象一下,如果你能用自然语言与你的开发环境对话,让它为你搜索代码库、管理项目任务,甚至直接在你最喜欢的代码托管平台GitHub上执行操作,那将会是怎样一种颠覆性的体验? 这并非遥不可及的科幻场景,而是已经可以实现的强大功能。本文将为你揭开这层神秘的面纱,通过一个名为“蓝耘”的平台(或任何支持此类功能的类似平台),一步步指导你从零开始构建一个基础的自动化工作流。更令人兴奋的是,我们将向你展示如何将这个工作流与强大的GitHub MCP(Multi-Capability Platform)工具无缝集成,从而赋予你的工作流直接与GitHub仓库进行深度交互的能力。 无论你是希望快速检索海量开源项目、自动追踪和创建任务(Issues),还是希望简化代码提交与拉取请求(Pull Request)的流程,本文都将为你提供详尽的、可操作的指南。我们将深入每一个步骤,从最基础的节点设置,到获取关键的GitHub密钥,再到最终实战演练,让你亲

By Ne0inhk
如何更新Git Bash:简单几步保持你的Git工具最新

如何更新Git Bash:简单几步保持你的Git工具最新

目录 目录 目录 前言 为什么需要更新Git Bash 检查当前Git版本 方法一:通过官方安装程序更新(推荐) 步骤详解 方法二:使用Git Bash内置更新命令(不推荐) 步骤详解 验证更新结果 更新后的配置检查 总结 前言 分享几种更新Git Bash的方法,让你的版本控制工具始终保持最新状态。 在日常开发工作中,Git Bash是许多开发者的得力工具,但经常被忽略的是定期更新它以确保使用最新功能和安全性补丁。本文将详细介绍几种更新Git Bash的方法。 备注:         Windows版本:Win11 24H2         Git Bash版本:2.51.1(截止发文当天,最新版) 为什么需要更新Git Bash 更新Git Bash可以带来许多好处: * 获取最新功能:新版本通常会引入有用的新命令和特性 * 修复已知错误:解决旧版本中存在的问题和漏洞 * 安全性增强:修补安全漏洞,

By Ne0inhk
开源大模型实战:GPT-OSS本地部署与全面测评

开源大模型实战:GPT-OSS本地部署与全面测评

文章目录 * 一、引言 * 二、安装Ollama * 三、Linux部署GPT-OSS-20B模型 * 四、模型测试 * 4.1 AI幻觉检测题 * 题目1:虚假历史事件 * 题目2:不存在的科学概念 * 题目3:虚构的地理信息 * 题目4:错误的数学常识 * 题目5:虚假的生物学事实 * 4.2 算法题测试 * 题目1:动态规划 - 最长公共子序列 * 题目2:图算法 - 岛屿数量 * 4.3 SQL题测试 * 题目1:复杂查询 - 员工薪资排名 * 题目2:数据分析 - 连续登录用户 * 题目3:窗口函数 - 移动平均 * 4.4

By Ne0inhk

GitHub网络加速完整解决方案:轻松突破访问限制

GitHub网络加速完整解决方案:轻松突破访问限制 【免费下载链接】hostsGitHub最新hosts。解决GitHub图片无法显示,加速GitHub网页浏览。 项目地址: https://gitcode.com/gh_mirrors/host/hosts GitHub Hosts项目是一个专为开发者设计的开源工具,通过智能优化hosts配置,有效解决GitHub图片无法显示、页面加载缓慢等常见网络问题。这个基于TypeScript开发的项目提供了多种配置方案,让您能够轻松享受流畅的GitHub访问体验。 🚀 项目核心价值 快速网络访问:通过精心测试的IP地址映射,绕过传统DNS解析瓶颈,实现直接快速访问GitHub服务。 全平台兼容性:完美支持macOS、Windows、Linux等主流操作系统,无论您使用哪种开发环境都能轻松部署。 自动化更新机制:支持定时获取最新IP配置,确保长期稳定的访问体验,无需手动维护。 零成本解决方案:完全免费开源,无需额外付费服务,为开发者提供经济高效的网络优化方案。 📋 快速配置指南 第一步:获取项目文件 # 克隆项目仓库

By Ne0inhk