JDK8新特性-Date-Time API
Java 8 Date-Time API 详解从 JDK7 的混乱到新 API 的清晰一、JDK7 及之前我们处理日期时间有多痛苦在 JDK7 时代处理日期时间主要依赖java.util.Date和java.util.Calendar。这两个类的设计存在严重缺陷导致开发中频繁出错。1.1java.util.Date的设计缺陷缺陷一命名和实际功能不符Date这个名字听起来只应该表示日期但它实际上存储的是日期 时间 毫秒的完整时间戳。// JDK7 Date now new Date(); // 这里面有年月日时分秒毫秒不只是日期缺陷二年份计算反人类Date的构造函数要求年份减去 1900// 创建 2024年1月1日却要这样写 Date date new Date(2024 - 1900, 0, 1); // 第一个参数是减去1900后的值为什么要这样因为Date内部用一个long毫秒值存储为了兼容旧系统构造函数保留了这种从 1900 年偏移的设计。这导致每个开发者都得在心里做减法。缺陷三月份从 0 开始Date date new Date(2024 - 1900, 0, 1); // 0 代表一月11 代表十二月计算机里数组从 0 开始可以理解但日历月份从 0 开始完全违背人类直觉。每年因为new Date(2024, 1, 1)被误当成1月1日实际上是2月1日而产生的 bug 不计其数。缺陷四对象是可变的Mutable—— 现成不安全的Date date new Date(); date.setTime(System.currentTimeMillis() 86400000); // 直接修改了对象内部状态这意味着你把一个Date对象传给另一个方法后那个方法可能偷偷修改它。在多线程环境下这会导致不可预期的结果。不可预测的可变状态是并发 bug 的主要来源之一。缺陷五toString()输出混乱且带隐式时区Date now new Date(); System.out.println(now); // 输出类似Wed Jul 30 10:44:00 CST 2026注意这个CST中国标准时间。但Date对象内部存储的其实是 UTC 毫秒数toString()却偷偷用了系统默认时区来格式化。这导致很多开发者误以为Date对象包含时区信息——实际上它并不包含。1.2java.util.Calendar的问题Calendar是为了弥补Date的不足而设计的但它同样糟糕// 获取当前年份 Calendar cal Calendar.getInstance(); int year cal.get(Calendar.YEAR); // 还好年份是正常的 // 获取月份 int month cal.get(Calendar.MONTH); // 又是从 0 开始0一月 // 设置日期 cal.set(Calendar.DAY_OF_MONTH, 32); // 如果当月没有32号会自动进位到下个月 // 但很多时候这不是你想要的行为它静默地纠正了你的错误输入Calendar也是可变的同样存在线程安全问题。而且它的 API 设计非常啰嗦完成一个简单的日期加减需要写很多行代码。1.3SimpleDateFormat的线程安全灾难格式化日期在 JDK7 里用SimpleDateFormatSimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd); // 单线程下没问题 String str sdf.format(new Date()); // 但如果你把它定义成 static 共享变量多线程同时访问时 // 会抛出各种异常或者输出完全错误的结果SimpleDateFormat内部维护了一个共享的日历对象多线程并发修改时就会互相干扰。这意味着每个线程都得自己创建实例或者用ThreadLocal包装增加了不必要的复杂度。1.4 时区处理几乎没有清晰的 APIJDK7 的Date不保存时区信息但它却依赖系统默认时区来显示。如果你需要处理纽约时间 2024年1月1日 12:00这样的概念没有直接的类可以表达只能手动计算毫秒偏移量极易出错。二、Java 8 Date-Time API 的设计思路Java 8 引入了全新的java.time包JSR-310它完全抛弃了Date和Calendar的设计基于以下核心原则重新构建原则 1不可变性Immutable所有核心类都是不可变的。一旦创建任何修改操作都会返回一个全新的对象原对象保持不变。LocalDate date LocalDate.of(2024, 7, 30); LocalDate nextDay date.plusDays(1); // date 本身还是 7月30日nextDay 是新的 7月31日为什么这样设计因为日期时间是一种值类型就像String或Integer一样修改它的值在语义上应该是创建一个新值而不是改变原来的值。不可变性天然保证了线程安全不需要额外的同步措施。原则 2职责分离不再用一个类包揽一切而是把不同的概念拆分成不同的类类职责LocalDate只表示日期年月日没有时间没有时区LocalTime只表示时间时分秒纳秒没有日期没有时区LocalDateTime日期 时间不带时区Instant时间戳距离 1970-01-01T00:00:00Z 的纳秒数机器视角ZonedDateTime日期 时间 时区完整的时间点Duration两个时间点之间的间隔基于时间的量如秒、纳秒Period两个日期之间的间隔基于日期的量如年、月、日原则 3符合人类直觉的索引月份从1开始1一月12十二月。年份就是实际年份不需要减去 1900。原则 4显式处理时区时区不再是隐式的系统默认设置而是显式的ZoneId对象你必须明确指定时区或者明确声明我不关心时区。三、核心类详解3.1LocalDate纯日期表示一个不带时间的日期比如2024年7月30日。// 创建方式 LocalDate today LocalDate.now(); // 当前日期 LocalDate specific LocalDate.of(2024, 7, 30); // 指定日期 LocalDate parsed LocalDate.parse(2024-07-30); // 从字符串解析默认格式 ISO-8601 // 获取字段 int year today.getYear(); // 2024 int month today.getMonthValue(); // 7从1开始 int day today.getDayOfMonth(); // 30 // 没有 setYear()不可变对象不允许修改 // 要用 withXxx() 创建新对象 LocalDate modified today.withYear(2025); // 返回 2025-07-30today 本身不变 // 日期加减 LocalDate tomorrow today.plusDays(1); LocalDate lastMonth today.minusMonths(1); LocalDate nextWeek today.plusWeeks(1); // 比较 boolean isBefore today.isBefore(tomorrow); // true boolean isAfter today.isAfter(tomorrow); // false设计意图LocalDate专门处理生日、保质期、合同签订日这类只关心日期、不关心几点几分的场景。它明确告诉你这里没有时间也没有时区。3.2LocalTime纯时间表示一天中的一个时刻比如14:30:00不带日期不带时区。LocalTime now LocalTime.now(); // 当前时间 LocalTime specific LocalTime.of(14, 30, 0); // 14:30:00 LocalTime parsed LocalTime.parse(14:30:00); LocalTime later now.plusHours(2); // 加2小时 LocalTime truncated now.withMinute(0).withSecond(0); // 整点3.3LocalDateTime日期 时间但仍不带时区LocalDateTime now LocalDateTime.now(); // 当前日期时间 LocalDateTime specific LocalDateTime.of(2024, 7, 30, 14, 30, 0); // 从 LocalDate 和 LocalTime 组合 LocalDate date LocalDate.of(2024, 7, 30); LocalTime time LocalTime.of(14, 30); LocalDateTime dt LocalDateTime.of(date, time);关键点LocalDateTime仍然不携带时区信息。它表示的是2024年7月30日14点30分这个本地视角的概念就像你在日历上写下的一个约定但没有说明这是北京时间、纽约时间还是伦敦时间。如果你需要明确的全球唯一时间点比如记录服务器日志、记录事件发生时刻不能用LocalDateTime要用Instant或ZonedDateTime。3.4Instant机器时间戳Instant表示的是 UTC 时间轴上的一个绝对点精确到纳秒。它等价于旧的System.currentTimeMillis()但更精确API 更清晰。Instant now Instant.now(); // 获取当前 UTC 时间戳 // 加减 Instant later now.plusSeconds(3600); // 1小时后 Instant earlier now.minusMillis(500); // 500毫秒前 // 获取毫秒数兼容旧系统 long millis now.toEpochMilli(); // 从旧 Date 转换 Date oldDate new Date(); Instant instant oldDate.toInstant(); // 转回旧 Date Date back Date.from(instant);设计意图Instant是没有人类可读格式的纯机器时间。它最适合记录事件发生顺序、计算超时、打日志时间戳。因为它基于 UTC所以全球任何服务器上的Instant.now()在理论上应该是相同的忽略时钟差异。3.5ZonedDateTime带时区的完整时间当你确实需要表达北京时间 2024年7月30日 14:30这个完整概念时// 当前系统默认时区的日期时间 ZonedDateTime now ZonedDateTime.now(); // 指定时区 ZonedDateTime nyTime ZonedDateTime.of( 2024, 7, 30, 14, 30, 0, 0, ZoneId.of(America/New_York) ); // 时区转换把纽约时间转成东京时间 ZonedDateTime tokyoTime nyTime.withZoneSameInstant(ZoneId.of(Asia/Tokyo));设计意图ZonedDateTime明确回答了三个问题什么时候日期时间、在哪里时区、对应全球时间轴上的哪个点通过 Instant 可以获取。时区转换也变得直接withZoneSameInstant()会自动处理夏令时等复杂规则。3.6Duration和Period两种不同的时间间隔这是 JDK7 最混乱的地方之一日期加减和时间段计算没有区分清楚。Java 8 把它们分开了Duration基于时间的精确间隔适合机器计算Instant start Instant.now(); // ... 执行一些操作 Instant end Instant.now(); Duration elapsed Duration.between(start, end); long millis elapsed.toMillis(); // 间隔多少毫秒 // 也可以直接构造 Duration twoHours Duration.ofHours(2);Period基于日历的日期间隔适合人类概念LocalDate startDate LocalDate.of(2024, 1, 1); LocalDate endDate LocalDate.of(2024, 7, 30); Period period Period.between(startDate, endDate); int months period.getMonths(); // 6 int days period.getDays(); // 29 // 表示1年2个月3天 Period p Period.of(1, 2, 3);为什么要分开因为1个月后对人类来说很明确但对机器来说不精确。1月31日加1个月是2月28日或29日这种日历逻辑和加 2,592,000 秒完全不同。Period保留年月日的语义Duration保留秒和纳秒的精确语义。3.7DateTimeFormatter线程安全的格式化替代了SimpleDateFormat而且设计为不可变、线程安全。// 预定义格式 LocalDate date LocalDate.now(); String iso date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2024-07-30 // 自定义格式 DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy年MM月dd日); String str date.format(formatter); // 2024年07月30日 // 解析 LocalDate parsed LocalDate.parse(2024年07月30日, formatter); // 带时区的格式 DateTimeFormatter zFormatter DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss z); String zStr ZonedDateTime.now().format(zFormatter);因为DateTimeFormatter是不可变的你可以把它定义成static final全局共享多线程并发使用也不会出问题。四、完整对比JDK7 vs JDK8场景计算今天是星期几30天后是什么日期并格式化输出JDK7 写法import java.util.Date; import java.util.Calendar; import java.text.SimpleDateFormat; public class DateDemo { public static void main(String[] args) { // 获取今天 Calendar cal Calendar.getInstance(); // 星期几1周日2周一... 非常反直觉 int dayOfWeek cal.get(Calendar.DAY_OF_WEEK); System.out.println(今天是星期 (dayOfWeek - 1)); // 需要手动转换 // 加30天 cal.add(Calendar.DAY_OF_MONTH, 30); Date future cal.getTime(); // 格式化注意SimpleDateFormat 不能共享 SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd); String result sdf.format(future); System.out.println(30天后是 result); } }JDK8 写法import java.time.LocalDate; import java.time.DayOfWeek; import java.time.format.DateTimeFormatter; public class DateDemo { public static void main(String[] args) { // 获取今天 LocalDate today LocalDate.now(); // 星期几枚举类型语义清晰 DayOfWeek dayOfWeek today.getDayOfWeek(); System.out.println(今天是 dayOfWeek); // 直接输出 MONDAY, TUESDAY 等 // 加30天 LocalDate future today.plusDays(30); // 格式化formatter 可以安全地定义为 static final String result future.format(DateTimeFormatter.ISO_LOCAL_DATE); System.out.println(30天后是 result); } }对比总结方面JDK7JDK8获取今天Calendar.getInstance()LocalDate.now()星期几数字 1-7含义模糊DayOfWeek枚举语义明确日期加减cal.add(field, amount)可变对象plusDays()返回新对象格式化类SimpleDateFormat线程不安全DateTimeFormatter线程安全代码清晰度需要理解 Calendar 的常量体系方法名自解释五、新旧 API 的互操作Java 8 没有删除旧的Date和Calendar而是提供了桥接方法方便你逐步迁移// Date → Instant → LocalDateTime Date oldDate new Date(); Instant instant oldDate.toInstant(); LocalDateTime ldt LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); // LocalDateTime → Instant → Date LocalDateTime newDateTime LocalDateTime.now(); Instant instant2 newDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date backToOld Date.from(instant2); // TimestampSQL↔ LocalDateTime java.sql.Timestamp timestamp java.sql.Timestamp.valueOf(localDateTime); LocalDateTime fromTimestamp timestamp.toLocalDateTime();六、总结Date-Time API 解决了什么问题JDK7 的弊端Java 8 的解决方案Date命名误导实际存储日期时间LocalDate、LocalTime、LocalDateTime职责分离年份要减 1900月份从 0 开始年份就是实际值月份从 1 开始对象可变线程不安全所有对象不可变天然线程安全SimpleDateFormat线程不安全DateTimeFormatter不可变且线程安全时区隐式、混乱ZonedDateTime显式处理时区Instant提供全球统一时间戳日期加减没有区分日历语义和时间语义Period和Duration分开处理格式化模式字符串容易写错且难以调试格式化器设计更严谨API 更一致核心设计思想日期时间不是一个值而是一组不同维度的概念日期、时间、时区、间隔。旧 API 试图用一个类解决所有问题结果一团糟。新 API 承认这些概念的独立性给每个概念一个专门的类每个类只做一件事但把它做好。

相关新闻

小众且高级✨2026学术定稿首选的沉浸式论文工具

小众且高级✨2026学术定稿首选的沉浸式论文工具

慢慢发现,优质的学术工具,从来都不喧嚣。 市面上大多论文工具主打多功能堆砌、流量营销,徒有其表,适配不了严苛的高校盲审与双检体系。 而OKBIYE是为数不多,深耕国内学术赛道、专注论文合规与品质的小众实力派。 没…

2026/7/30 18:17:43 阅读更多 →
编译原理笔记 2025/4/22

编译原理笔记 2025/4/22

基本概念汇编语言与高级程序设计语言的关系/汇编干嘛的:高级语言与硬件无关,汇编语言的定义与CPU的指令系统直接相关。只要将高级语言编写的程序等价地转换成特定硬件平台所支持的方式来实现(汇编程序或机器指令序列),…

2026/7/30 18:17:43 阅读更多 →
5个实战场景深度解析:如何用GBrain智能大脑解决知识管理痛点?

5个实战场景深度解析:如何用GBrain智能大脑解决知识管理痛点?

5个实战场景深度解析:如何用GBrain智能大脑解决知识管理痛点? 【免费下载链接】gbrain Garrys Opinionated OpenClaw/Hermes Agent Brain 项目地址: https://gitcode.com/gh_mirrors/gb/gbrain 你是否曾花费数小时在堆积如山的笔记中寻找某个会议…

2026/7/30 18:17:43 阅读更多 →

最新新闻

11:晶晶赴约会

11:晶晶赴约会

/*** 题目名称&#xff1a;晶晶赴约会 <p>* 题目来源&#xff1a;http://noi.openjudge.cn/ch0104/11/ <p>* 程序功能&#xff1a;根据给定看展览的日期判断晶晶能否赴约会&#xff0c;并输出对应的字符串** author 潘磊&#xff0c;just_panleijust.edu.cn* versi…

2026/7/30 18:27:46 阅读更多 →
PxMatrix:ESP8266/ESP32 LED矩阵显示库的终极指南

PxMatrix:ESP8266/ESP32 LED矩阵显示库的终极指南

PxMatrix&#xff1a;ESP8266/ESP32 LED矩阵显示库的终极指南 【免费下载链接】PxMatrix Adafruit GFX compatible graphics driver for LED matrix panels 项目地址: https://gitcode.com/gh_mirrors/px/PxMatrix 想要在廉价的RGB LED矩阵上实现惊艳的视觉效果吗&#…

2026/7/30 18:27:46 阅读更多 →
棱镜AI工作流入门指南:新手如何快速上手AI自动化工作

棱镜AI工作流入门指南:新手如何快速上手AI自动化工作

在数字化浪潮席卷各行各业的当下&#xff0c;越来越多的团队和个人开始寻求更高效的工作方式。面对日常办公中繁琐的重复操作、内容创作时的灵感枯竭、业务流程中的效率瓶颈&#xff0c;一种新型解决方案正在悄然改变传统工作模式。一、智能时代的效率革命现代办公环境中&#…

2026/7/30 18:27:45 阅读更多 →
如何快速上手res-downloader:全网视频资源下载的完整指南

如何快速上手res-downloader:全网视频资源下载的完整指南

如何快速上手res-downloader&#xff1a;全网视频资源下载的完整指南 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 还在为无…

2026/7/30 18:27:45 阅读更多 →
终极电脑健康管家:免费开源硬件监控工具LibreHardwareMonitor完全指南

终极电脑健康管家:免费开源硬件监控工具LibreHardwareMonitor完全指南

终极电脑健康管家&#xff1a;免费开源硬件监控工具LibreHardwareMonitor完全指南 【免费下载链接】LibreHardwareMonitor Libre Hardware Monitor is free software that can monitor the temperature sensors, fan speeds, voltages, load and clock speeds of your computer…

2026/7/30 18:27:45 阅读更多 →
06:判断是否为两位数

06:判断是否为两位数

/*** 题目名称&#xff1a;判断是否为两位数 <p>* 题目来源&#xff1a;http://noi.openjudge.cn/ch0104/06/ <p>* 程序功能&#xff1a;根据指定整数是否为两位数输出对应的数字** author 潘磊&#xff0c;just_panleijust.edu.cn* version 1.0*/import java.util…

2026/7/30 18:26:45 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具&#xff1a;DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼&#xff1f;是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper&#xff1a;网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具&#xff0c;它并非替代教师&#xff0c;而是通过语义理解、知识图谱与多模态生成能力&#xff0c;将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档&#xff0c;可以直接使用&#xff01;系统支持图片、视频、摄像头等多种方式检测裂缝&#xff0c;功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像&#xff01; pubg绝地求生目标检测数据集 1分类&#xff1a;e_body&#xff0c;14905个标签&#xff0c;txt格式 共计14244张图&#xff0c;99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别&#xff1a; allies enemy tag图片总量&#xff1a;7247张训练集&#xff1a;5139张验证集&#xff1a;1425张测试集&#xff1a;683张标注状态&#xff1a;全部已标注&#xff0c;即拿即用数据格式&#xff1a;支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻