Java 日期时间类全面解析
Java 日期时间类全面解析:从传统到现代的演进
一、发展历程概览
二、传统日期类(Java 8前)
1. java.util.Date
- 日期表示类
Date now = new Date(); // 当前日期时间
System.out.println(now); // Wed May 15 09:30:45 CST 2023// 特定时间创建
Date specificDate = new Date(121, 4, 15); // 2021-05-15 (已弃用)
主要问题:
- 年份从1900开始计数
- 月份0-11(实际需+1)
- 线程不安全
- 时区处理混乱
2. java.util.Calendar
- 日期操作类
Calendar cal = Calendar.getInstance();
cal.set(2023, Calendar.MAY, 15); // 2023-05-15// 日期计算
cal.add(Calendar.DAY_OF_MONTH, 7); // 加7天// 获取值
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1; // 月份需+1
缺点:
- API设计臃肿
- 可变对象(线程不安全)
- 仍存在月份偏移问题
3. java.text.SimpleDateFormat
- 日期格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf.format(new Date()); // 2023-05-15 09:30:45// 解析日期
Date parsedDate = sdf.parse("2023-05-15 12:00:00");
致命缺陷:
- 非线程安全(必须在方法内创建或使用ThreadLocal)
三、现代日期时间API(Java 8+)
java.time
包提供了全新的日期时间处理API:
1. 核心类对比表
类名 | 描述 | 示例值 |
---|---|---|
LocalDate | 只包含日期 | 2023-05-15 |
LocalTime | 只包含时间 | 09:30:45 |
LocalDateTime | 日期+时间 | 2023-05-15T09:30:45 |
ZonedDateTime | 带时区的日期时间 | 2023-05-15T09:30:45+08:00[Asia/Shanghai] |
Instant | 时间戳(Unix时间) | 1684114245 |
Period | 日期间隔(年/月/日) | P1Y2M3D |
Duration | 时间间隔(秒/毫秒) | PT8H30M |
2. 基础使用示例
// 获取当前日期
LocalDate today = LocalDate.now();// 创建特定日期
LocalDate birthday = LocalDate.of(1990, Month.DECEMBER, 25);// 日期计算
LocalDate nextWeek = today.plusWeeks(1);
LocalDate previousMonth = today.minusMonths(1);// 日期比较
boolean isAfter = today.isAfter(birthday);
boolean isLeapYear = today.isLeapYear();
3. 时间操作
LocalTime nowTime = LocalTime.now();
LocalTime meetingTime = LocalTime.of(14, 30); // 14:30// 时间加减
LocalTime lunchTime = nowTime.plusHours(1).plusMinutes(30);// 时间判断
if (nowTime.isBefore(LocalTime.NOON)) {System.out.println("上午好!");
}
4. 日期时间组合
LocalDateTime meetingDateTime = LocalDateTime.of(2023, Month.MAY, 15, 14, 30);// 转换为时区时间
ZonedDateTime shanghaiMeeting = meetingDateTime.atZone(ZoneId.of("Asia/Shanghai"));// 转换为其他时区
ZonedDateTime newYorkMeeting = shanghaiMeeting.withZoneSameInstant(ZoneId.of("America/New_York"));
5. 时间间隔计算
// 日期间隔(年/月/日)
Period period = Period.between(LocalDate.of(2020, 1, 1), LocalDate.now()
);
System.out.println(period.getYears() + "年" + period.getMonths() + "月");// 时间间隔(精确时间)
Duration duration = Duration.between(LocalTime.of(9, 0), LocalTime.now()
);
System.out.println(duration.toMinutes() + "分钟");
四、格式化与解析
1. DateTimeFormatter
- 替代SimpleDateFormat
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());// 格式化
String formatted = LocalDateTime.now().format(formatter);// 解析
LocalDateTime parsed = LocalDateTime.parse("2023-05-15 14:30:00", formatter);
2. 预定义格式器
// ISO标准格式
String isoFormat = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);// 本地化格式
DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.CHINA);String chineseFormat = LocalDateTime.now().format(localizedFormatter);
五、与传统类的转换
// Date 转 Instant
Date legacyDate = new Date();
Instant instant = legacyDate.toInstant();// Instant 转 Date
Date newDate = Date.from(Instant.now());// Calendar 转 ZonedDateTime
Calendar calendar = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId()
);
六、最佳实践指南
-
版本选择:
- Java 8+项目:始终使用java.time
- 旧项目兼容:使用Joda-Time(第三方库)
-
时区处理原则:
// 明确时区而非依赖系统默认 ZonedDateTime zonedNow = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));// UTC时间优先存储 Instant utcInstant = Instant.now();
-
避免使用枚举值:
// 推荐 LocalDate date = LocalDate.of(2023, Month.MAY, 15);// 不推荐(可能因月份偏移引发错误) LocalDate date = LocalDate.of(2023, 5, 15);
-
线程安全实践:
// DateTimeFormatter线程安全可共享 public static final DateTimeFormatter GLOBAL_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;// SimpleDateFormat必须每个线程独立实例 private static final ThreadLocal<SimpleDateFormat> threadLocalSdf = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
七、经典问题解决方案
1. 工作日计算
LocalDate start = LocalDate.of(2023, 1, 1);
LocalDate end = LocalDate.of(2023, 12, 31);long workDays = Stream.iterate(start, date -> date.plusDays(1)).limit(ChronoUnit.DAYS.between(start, end)).filter(date -> date.getDayOfWeek() != DayOfWeek.SATURDAY).filter(date -> date.getDayOfWeek() != DayOfWeek.SUNDAY).count();
2. 夏令时处理
ZoneId zone = ZoneId.of("America/New_York");
ZonedDateTime springTime = ZonedDateTime.of(2023, 3, 12, 2, 30, 0, 0, zone);// 自动处理时间跳变(会调整为03:30)
System.out.println(springTime); // 2023-03-12T03:30-04:00[America/New_York]
3. 精确时间计算
Instant start = Instant.now();
// 执行操作...
Instant end = Instant.now();Duration elapsed = Duration.between(start, end);
System.out.printf("操作耗时: %d毫秒", elapsed.toMillis());
八、Joda-Time(老项目备用方案)
// 引入依赖
implementation 'joda-time:joda-time:2.12.5'// 使用示例
DateTime now = new DateTime();
DateTime nextWeek = now.plusWeeks(1);
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");
String formatted = fmt.print(now);
总结思考
-
演进本质:
- 从可变对象 → 不可变对象(线程安全)
- 从过程式操作 → 流畅API
- 从隐含规则 → 显式表达
-
选择策略:
场景 推荐方案 新项目 java.time Android项目 java.time + ThreeTenABP Java 7及以下 Joda-Time 简单日期操作 LocalDate/LocalTime 全球时间系统 Instant/ZonedDateTime -
设计启示:
- 清晰性:消除月份偏移等隐含规则
- 类型安全:专用类型处理不同时间概念
- 领域驱动:方法命名直击业务语义(plusDays()、isAfter())
最终建议:所有新项目应优先使用java.time API,老项目逐步迁移。掌握现代日期时间API,是构建健壮时间敏感型应用的基石。
相关文章:

Java 日期时间类全面解析
Java 日期时间类全面解析:从传统到现代的演进 一、发展历程概览 二、传统日期类(Java 8前) 1. java.util.Date - 日期表示类 Date now new Date(); // 当前日期时间 System.out.println(now); // Wed May 15 09:30:45 CST 2023// 特定时间…...

【工具-Wireshark 抓包工具】
工具-Wireshark 抓包工具 ■ Wireshark 抓包工具■ 通过IP指定查看■■ ■ Wireshark 抓包工具 抓包工具】win 10 / win 11:WireShark 下载、安装、使用 Wireshark下载 阿里云镜像 ■ 通过IP指定查看 ■ ■...
Linux安全机制:从SELinux到Intel SGX的堡垒
Linux安全机制:从SELinux到Intel SGX的堡垒 数字世界的钢铁长城 引言:操作系统的"防御工事" 当服务器每天承受数百万次攻击尝试时,Linux内核的安全机制如同精密的防御系统,在纳秒级时间内做出响应。现代Linux安全架构已…...

设备驱动与文件系统:06 目录与文件
磁盘使用的最后一层抽象:文件系统 今天我们讲第31讲,这一讲将完成磁盘对磁盘使用的最后一层抽象。对此板使用最后一层抽象,抽象出来的是什么呢? 实际上我们使用过磁盘,大家应该有这样的认识,最后不管这个磁…...
C++11 Token Bucket (令牌桶)算法的锁无实现及应用
Token Bucket(令牌桶)算法是一种在流量控制和资源分配领域被广泛应用的技术。它通过约束数据传输速率或任务执行频率,确保系统在资源有限的情况下,能够稳定、高效地运行,避免因突发流量或任务积压而导致的性能下降甚至…...
详细介绍uni-app中Composition API和Options API的使用方法
uni-app 中 Composition API 和 Options API 的使用方法详解 一、Options API(Vue 2.x 传统方式) 1. 基本结构 Options API 通过配置对象的不同选项(如 data、methods、computed 等)组织代码: <template><…...
delphi7 链表 使用方法
在 Delphi 中,链表是一种常见的数据结构,用于存储一系列的元素,其中每个元素都包含一个指向列表中下一个元素的引用。在 Delphi 7 中,你可以手动实现链表,或者使用一些现有的集合类,例如 TList 或者 TLinke…...

Linux 系统中的算法技巧与性能优化
引言 Linux 系统以其开源、稳定和高度可定制的特性,在服务器端、嵌入式设备以及开发环境中得到了极为广泛的应用。对于开发者而言,不仅要掌握在 Linux 环境下实现各类算法的方法,更要知晓如何利用系统特性对算法进行优化,以提升…...

【C++系列】模板类型特例化
1. C模板类型特例化介绍 定义:模板类型特例化(Template Specialization)是C中为模板的特定类型提供定制实现的机制,允许开发者对通用模板无法处理的特殊类型进行优化或特殊处理。 产生标准: C98/03…...

K8S认证|CKS题库+答案| 7. Dockerfile 检测
目录 7. Dockerfile 检测 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、修改 Dockerfile 3)、 修改 deployment.yaml 7. Dockerfile 检测 免费获取并激活 CKA_v1.31_模拟系统 题目 您必须在以…...
JAVA 对象 详解
对象 对象结构: 对象头(元数据和指向class的指针)、实例数据、对齐填充 数组对象: 对象头(元数据和指向class的指针)、数组长度、数组数据、对齐填充 对象创建: 一、当Java虚拟机遇到一条…...
MATLAB实战:四旋翼姿态控制仿真方案
以下是一个基于MATLAB/Simulink的四旋翼姿态控制仿真方案。本方案使用简化姿态动力学模型,并设计PID控制器进行稳定控制。 1. 四旋翼姿态动力学模型 核心方程:I * ω̇ ω (I * ω) τ 其中: I diag([Ixx, Iyy, Izz]) 为转动惯量矩阵 …...

基于Scala实现Flink的三种基本时间窗口操作
目录 代码结构 代码解析 (1) 主程序入口 (2) 窗口联结(Window Join) (3) 间隔联结(Interval Join) (4) 窗口同组联结(CoGroup) (5) 执行任务 代码优化 (1) 时间戳分配 (2) 窗口大小 (3) 输出格式…...

c++对halcon的动态链接库dll封装及调用(细细讲)
七个部分(是个大工程) 一,halcon封装函数导出cpp的内容介绍 二,c++中对halcon环境的配置 三,在配置环境下验证halcon代码 四,dll项目创建+环境配置 五,编辑dll及导出 六,调用打包好的动态链接库的配置 七,进行测试 一,halcon的封装及导出cpp的介绍 1,我这里…...

【优选算法】分治
一:颜色分类 class Solution { public:void sortColors(vector<int>& nums) {// 三指针法int n nums.size();int left -1, right n, i 0;while(i < right){if(nums[i] 0) swap(nums[left], nums[i]);else if(nums[i] 2) swap(nums[--right], num…...
QGraphicsView中鼠标点击与移动事件传递给MainWindow
在Qt图形应用程序开发中,QGraphicsView和QGraphicsScene框架提供了强大的2D图形显示功能。然而,当我们需要在主窗口(MainWindow)中处理这些视图中的鼠标事件。 问题背景 在典型的Qt图形应用程序架构中: MainWindow └── QGraphicsView└── QGraphicsScene└── QGra…...

【图片识别改名】如何批量将图片按图片上文字重命名?自动批量识别图片文字并命名,基于图片文字内容改名,WPF和京东ocr识别的解决方案
应用场景 在日常工作和生活中,我们经常会遇到需要对大量图片进行重命名的情况。例如,设计师可能需要根据图片内容为设计素材命名,文档管理人员可能需要根据扫描文档中的文字对图片进行分类命名。传统的手动重命名方式效率低下且容易出错&…...

RabbitMQ 的高可用性
RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用的RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。 单机模式 单机模式,生产几乎不用。 普通集群模式(无高可用性) 普通集群模…...
DAY 48 随机函数与广播机制
知识点回顾: 随机张量的生成:torch.randn函数卷积和池化的计算公式(可以不掌握,会自动计算的)pytorch的广播机制:加法和乘法的广播机制 ps:numpy运算也有类似的广播机制,基本一致 作…...
计算机基础知识(第五篇)
计算机基础知识(第五篇) 架构演化与维护 软件架构的演化和定义 软件架构的演化和维护就是对架构进行修改和完善的过程,目的就是为了使软件能够适应环境的变化而进行的纠错性修改和完善性修改等,是一个不断迭代的过程࿰…...
从零开始制作小程序简单概述
以下是结合案例的“从零制作小红书风格小程序”的全流程指南,采用小红书爆款笔记的结构呈现,并附CSDN参考资源👇: 一、核心开发步骤(附工具推荐) 账号与定位 ✅ 注册类型选择:个人店(…...

AI架构师修炼之道
1 AI时代的架构革命 与传统软件开发和软件架构师相比,AI架构师面临着三重范式转换: 1.1 技术维度,需处理异构算力调度与模型生命周期管理的复杂性; 1.2 系统维度,需平衡实时性与资源约束的矛盾; 1.3 价…...
三十五、面向对象底层逻辑-Spring MVC中AbstractXlsxStreamingView的设计
在Web应用开发中,大数据量的Excel导出功能是常见需求。传统Apache POI的XSSF实现方式在处理超大数据集时,会因全量加载到内存导致OOM(内存溢出)问题。Spring MVC提供的AbstractXlsxStreamingView通过流式处理机制,有效…...
Unity的日志管理类
脚本功能: 1,打印日志到控制台 2,显示日志到UI Text 3,将日志写入本地文件 这对unity开发安卓平台来说很有用 using System; using System.IO; using System.Text; using UnityEngine; using UnityEngine.UI;public class FileLo…...
【PhysUnits】17.2 配套变量结构体 Var(variable.rs)
一、源码 这段代码定义了一个泛型结构体 Var,用于封装数值类型并提供各种运算操作。 /** 变量结构体 Var* 该结构体泛型参数 T 需满足 Numeric 约束*/use core::ops::{Neg, Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign}; use crate::constant::Integer;…...

iview组件库:当后台返回到的数据与使用官网组件指定的字段不匹配时,进行修改某个属性名再将response数据渲染到页面上的处理
1、需求导入 当存在前端需要的数据的字段渲染到表格或者是一些公共的表格组件展示数据时的某个字段名与后台返回的字段不一致时,那么需要前端进行稍加处理,而不能直接this.list res.data;这样数据是渲染不出来的。 2、后台返回的数据类型 Datalist(pn) …...

服务器 | Centos 9 系统中,如何部署SpringBoot后端项目?
系列文章目录 虚拟机 | Ubuntu 安装流程以及界面太小问题解决 虚拟机 | Ubuntu图形化系统: open-vm-tools安装失败以及实现文件拖放 虚拟机 | Ubuntu操作系统:su和sudo理解及如何处理忘记root密码 文章目录 系列文章目录前言一、环境介绍二、 使用syst…...
qt network 整体框架
以下是 Qt 网络模块中 QNetworkInterface、TCP、UDP 及相关类的层次关系图及说明: 一、Qt 网络模块层次结构 ┌─────────────────────────────────────────────────────────────┐ │ QtNetwork 模…...
C++ map基础概念、map对象创建、map赋值操作、map大小操作、map数据插入、map数据删除、map数据修改、map数据统计
map的使用频率很高,仅次于vector,先了解下pair的概念: pair 概念: template<class _Ty1, class Ty2> struct pair{ _Ty1 first; // 这两个可以是任意的类型 _Ty2 second; }; eg:pair<int, int> p(13,…...

(2025)Windows修改JupyterNotebook的字体,使用JetBrains Mono
(JetBrains Mono字体未下载就配置,这种情况我不知道能不能行,没做过实验,因为我电脑已经下载了,不可能删了那么多字体做实验,我的建议是下载JetBrains Mono字体,当你使用VsCode配置里面的JetBrains字体也很有用) 首先参考该文章下载字体到电脑上 VSCode 修改字体为JetBrains …...