【Java系列】Java 8 日期/时间 API 简介

目录

1. 概述

2. 现有日期/时间 API 的问题

3. 使用 LocalDate/LocalTime/LocalDateTime API

3.1 LocalDate

3.2 LocalTime

3.3 LocalDateTime

4. 使用 ZonedDateTime API

5. 使用 Period and Duration API

5.1 Period

5.2 Duration

6. 与 Date 和 Calendar 的兼容性

7. 日期/时间格式化

8. 向后移植和替代选项

8.1. ThreeTen Project

8.2. Joda-Time Library

9. 小结


1. 概述

Java 8 引入了新的日期和时间 API,以解决旧版 java.util.Datejava.util.Calendar 的缺点。

在本教程中,我们从现有 Date 和 Calendar API 中的问题开始,讨论新的 Java 8 日期和时间 API 如何解决这些问题。

我们还将了解新 Java 8 项目的一些核心类,它们是 java.time 包的一部分,例如 LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Period、Duration 及其支持的 API。

2. 现有日期/时间 API 的问题

  • 线程安全 - Date Calendar 类不是线程安全的,这使得开发人员必须处理难以调试的并发问题,并编写额外的代码来处理线程安全。 相反,Java 8 中引入的新日期和时间 API 是不可变的且线程安全的,从而消除了开发人员的并发问题。
  • API 设计和易于理解 - Date Calendar API 设计不佳,没有足够的方法来执行日常操作。 新的日期/时间 API 以 ISO 为中心,并遵循 date、time、duration 和 periods 的一致领域模型。 有多种实用方法支持最常见的操作。
  • 时区 - 开发人员必须使用旧 API 编写额外的逻辑来处理时区逻辑,而使用新 API 时,可以使用 LocalZonedDate/Time API 来轻松处理时区问题。

3. 使用 LocalDate/LocalTime/LocalDateTime API

最常用的类是 LocalDate、LocalTimeLocalDateTime。 正如它们的名称所示,它们代表观察者上下文中的本地日期/时间。

当不需要在上下文中显式指定时区时,我们主要使用这些类。 作为本节的一部分,我们将介绍最常用的 API。

3.1 LocalDate

LocalDate 表示 ISO 格式 (yyyy-MM-dd) 的日期,不包含时间。 我们可以用它来存储生日和发薪日等日期。

可以从系统时钟创建当前日期的实例:

LocalDate localDate = LocalDate.now();

我们可以使用 of 方法或 parse 方法获取代表特定日、月、年的 LocalDate

例如,这些代码片段代表 2015 年 2 月 20 日的 LocalDate

LocalDate.of(2015, 02, 20);LocalDate.parse("2015-02-20");

LocalDate 提供了各种实用方法来获取各种信息。 让我们快速浏览一下其中一些 API 方法。

// 获取当前本地日期并添加一天
LocalDate tomorrow = LocalDate.now().plusDays(1);// 获取当前日期并减去一个月。请注意它如何接受枚举作为时间单位
LocalDate previousMonthSameDay = LocalDate.now().minus(1, ChronoUnit.MONTHS);// 解析日期"2016-06-12"并获取星期几。返回值是表示 DayOfWeek 的对象,对应int值范围从 1(星期一)到 7(星期日)。建议应用程序使用枚举而不是 int 值来确保代码清晰
DayOfWeek sunday = LocalDate.parse("2016-06-12").getDayOfWeek();// 解析日期"2016-06-12"并获取月份。返回值是表示月份的int值,范围从 1 到 31
int twelve = LocalDate.parse("2016-06-12").getDayOfMonth();// 测试某个日期是否出现在闰年
boolean leapYear = LocalDate.now().isLeapYear();// 确定一个日期与另一个日期的关系是在另一个日期之前还是之后发生
boolean notBefore = LocalDate.parse("2016-06-12").isBefore(LocalDate.parse("2016-06-11"));boolean isAfter = LocalDate.parse("2016-06-12").isAfter(LocalDate.parse("2016-06-11"));// 请注意:isBefore isAfter 方法没有包含关系。下面的示例都返回false
LocalDate a = LocalDate.of(2012, 6, 30);
boolean isFalse = a.isAfter(a);
boolean isFalse = a.isBefore(a);// 获取表示给定日期的当天开始 (2016-06-12T00:00) 的 LocalDateTime
LocalDateTime beginningOfDay = LocalDate.parse("2016-06-12").atStartOfDay();// 获取表示月份开始 (2016-06-01) 的 LocalDate
LocalDate firstDayOfMonth = LocalDate.parse("2016-06-12").with(TemporalAdjusters.firstDayOfMonth());

现在让我们看看如何使用 LocalTime。 

3.2 LocalTime

LocalTime 表示不带日期的时间。

LocalDate 类似,我们可以从系统时钟或使用 parse 和 of 方法创建 LocalTime 的实例。

现在我们将快速浏览一些常用的 API。

// 从系统时钟创建当前 LocalTime 的实例
LocalTime now = LocalTime.now();// 通过解析字符串来创建表示上午 6:30 的 LocalTime
LocalTime sixThirty = LocalTime.parse("06:30");// 使用工厂方法创建代表上午 6:30 的 LocalTime
LocalTime sixThirty = LocalTime.of(6, 30);// 通过解析字符串并使用"plus" API 添加一个小时来创建一个 LocalTime。结果将是代表上午 7:30 的 LocalTime
LocalTime sevenThirty = LocalTime.parse("06:30").plus(1, ChronoUnit.HOURS);// 有多种 get 方法可用于获取特定的时间单位,如小时、分钟和秒
int six = LocalTime.parse("06:30").getHour();// 检查一个特定时间是否在另一个特定时间之前或之后,下面示例将返回true
boolean isbefore = LocalTime.parse("06:30").isBefore(LocalTime.parse("07:30"));// 一天中的最大、最小和中午时间可以通过 LocalTime 类中的常量获得。当执行数据库查询以查找给定时间范围内的记录时,这非常有用。
LocalTime maxTime = LocalTime.MAX;
LocalTime min = LocalTime.MIN;
LocalTime noon = LocalTime.NOON;

现在让我们深入了解 LocalDateTime

3.3 LocalDateTime

该类提供了各种 API。 我们将看看一些最常用的。

// LocalDateTime 的实例可以从系统时钟获取,类似于 LocalDate 和 LocalTime
LocalDateTime.now();// 下面的代码示例解释了如何使用工厂"of"和"parse"方法创建实例。 结果将是一个代表 2015 年 2 月 20 日上午 6:30 的 LocalDateTime 实例
LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);
LocalDateTime.parse("2015-02-20T06:30:00");// 有一些实用程序 API 可以支持特定时间单位(例如天、月、年和分钟)的加法和减法。
// 下面的代码演示了"加"和"减"方法。 这些 API 的行为与 LocalDate 和 LocalTime 中的对应 API 完全相同
localDateTime.plusDays(1);
localDateTime.minusHours(2);// Getter 方法也可用于提取类似于日期和时间类的特定单位。 鉴于上面的 LocalDateTime 实例,此代码示例将返回二月
localDateTime.getMonth();

4. 使用 ZonedDateTime API

当我们需要处理特定于时区的日期和时间时,Java 8 提供了 ZonedDateTime。 ZoneId是用于表示不同区域的标识符。 大约有 40 个不同的时区,ZoneId 可以按照如下方式表示它们。

我们为上海创建一个时区:

ZoneId zoneId = ZoneId.of("Asia/Shanghai");

我们可以获得所有时区 ID 的集合:

Set<String> allZoneIds = ZoneId.getAvailableZoneIds();

LocalDateTime 可以转换为特定区域:

ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);

ZonedDateTime 提供了解析方法来获取特定于时区的日期时间:

ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Asia/Shanghai]");

使用时区的另一种方法是使用 OffsetDateTimeOffsetDateTime 是带有偏移量的日期时间的不可变表示形式。 此类存储所有日期和时间字段(精确到纳秒)以及与 UTC/Greenwich 的偏移量。

可以使用 ZoneOffset 创建 OffSetDateTime 实例。 在这里,我们创建一个代表 2015 年 2 月 20 日上午 6:30 的 LocalDateTime

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);

然后我们通过创建 ZoneOffset 并设置 localDateTime 实例来添加两个小时的时间:

ZoneOffset offset = ZoneOffset.of("+02:00");OffsetDateTime offSetByTwo = OffsetDateTime.of(localDateTime, offset);

我们现在的 localDateTime 为 2015-02-20 06:30 +02:00。

现在让我们继续讨论如何使用 Period Duration 类修改日期和时间值。

5. 使用 Period and Duration API

Period 类表示以年、月和日为单位的时间量,而 Duration 类表示以秒和纳秒为单位的时间量。

5.1 Period

Period 类广泛用于修改给定日期的值或获取两个日期之间的差异:

LocalDate initialDate = LocalDate.parse("2007-05-10");

我们可以使用 Period 来操作日期:

LocalDate finalDate = initialDate.plus(Period.ofDays(5));

Period 类具有各种 getter 方法,例如 getYearsgetMonths getDays,用于从 Period 对象获取对应的值。

例如,当我们尝试获取天数差异时,这将返回 int 值 5:

int five = Period.between(initialDate, finalDate).getDays();

 我们可以使用 ChronoUnit.Between 获取特定单位(例如天、月或年)中两个日期之间的 Period

long five = ChronoUnit.DAYS.between(initialDate, finalDate);

此代码示例返回五天。

让我们继续看一下 Duration 类。

5.2 Duration

Period 类似,Duration 类用于处理时间。

让我们创建一个 6:30 a.m. 的 LocalTime,然后添加 30 秒的 duration 时间以使 LocalTime 变为 6:30:30 a.m.:

LocalTime initialTime = LocalTime.of(6, 30, 0);LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));

我们可以将两个时间作为参数获取 Duration 的间隔时间。

首先,我们使用 Duration 类的 Between() 方法来查找 finalTime initialTime 之间的时间差,并返回以秒为单位的差值:

long thirty = Duration.between(initialTime, finalTime).getSeconds();

在第二个示例中,我们使用 ChronoUnit 类的 Between() 方法来执行相同的操作:

long thirty = ChronoUnit.SECONDS.between(initialTime, finalTime);

现在我们将了解如何将现有的 Date 和 Calendar 转换为新的日期/时间。

6. 与 Date 和 Calendar 的兼容性

Java 8 添加了 toInstant() 方法,该方法有助于将现有的 Date 和 Calendar 实例转换为新的日期和时间 API:

LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());

LocalDateTime 可以根据纪元秒构建。 以下代码的结果将是表示 2016-06-13T11:34:50 的 LocalDateTime:

LocalDateTime.ofEpochSecond(1465817690, 0, ZoneOffset.UTC);

现在让我们继续讨论日期和时间格式。

7. 日期/时间格式化

Java 8 提供了用于轻松格式化日期和时间的 API:

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.JANUARY, 25, 6, 30);

此代码传递 ISO 日期格式来格式化本地日期,结果为 2015-01-25:

String localDateString = localDateTime.format(DateTimeFormatter.ISO_DATE);

DateTimeFormatter 提供各种标准格式选项。

自定义模式也可以提供给 format 方法,这里返回一个 LocalDate 为 2015/01/25:

localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));

我们可以传入 SHORTLONG MEDIUM 格式样式作为格式选项的一部分。

例如,这将给出表示 25-Jan-2015, 06:30:00 的 LocalDateTime 的输出:

localDateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.UK));

让我们看一下 Java 8 核心日期/时间 API 的可用替代方案。

8. 向后移植和替代选项

8.1. ThreeTen Project

于正在从 Java 7 或 Java 6 迁移到 Java 8 并且想要使用日期和时间 API 的组织,ThreeTen 项目提供了向后移植功能。

开发人员可以使用此项目中提供的类来实现与新的 Java 8 日期和时间 API 相同的功能。 一旦他们迁移到 Java 8,就可以切换包。

ThreeTen 项目的工件可以在 Maven 中央存储库中找到:

<dependency><groupId>org.threeten</groupId><artifactId>threetenbp</artifactId><version>1.3.1</version>
</dependency>

8.2. Joda-Time Library

Java 8 日期和时间库的另一个替代方案是 Joda-Time 库。 事实上,Java 8 Date/Time API 是由 Joda-Time 库的作者 (Stephen Colebourne) 和 Oracle 共同领导的。 该库提供了 Java 8 日期/时间项目中支持的几乎所有功能。

通过在项目中包含以下 pom 依赖项来使用,可以在 Maven Central 中找到该工件:

<dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.9.4</version>
</dependency>

9. 小结

Java 8 提供了丰富的日期/时间 API,具有一致的API设计,使开发更容易。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络异常案例五_SYN被丢弃

问题现象 公司同事使用的时候&#xff0c;反馈系统不稳定&#xff0c;访问的时候&#xff0c;有时候会出现白屏&#xff08;连接超时&#xff09;&#xff0c;或者系统页面点击没有响应&#xff0c;过一会之后刷新系统又可以正常展示了。之前未收到过类似反馈&#xff0c;一直…

Axure 动态面板初使用 - 实现简单的Banner图轮播效果

使用工具版本 Axure 9 实现的效果 步骤过程 1、打开Axure工具&#xff0c;从元件库拖个动态面板到空白页&#xff1b; 2、给面板设置一个常用的banner尺寸&#xff0c;举个栗子&#xff1a;343151(移动端我常用的banner尺寸)&#xff0c;顺便给它起个名字&#xff0c;就叫…

RESTful API如何使用它构建web应用程序

RESTful API&#xff08;Representational State Transfer&#xff09;&#xff0c;即表现层状态转移&#xff0c;是一种通过 HTTP 协议传输数据的应用程序接口&#xff08;API&#xff09;设计风格。 RESTful API 的设计原则包括以下几个方面&#xff1a; 资源&#xff08;R…

QT学习日记 | 信号与槽

目录 前言 一、初始信号与槽 1、信号与槽的本质 2、信号与槽的使用 3、内置信号、内置槽函数与自定义信号、自定义槽函数 &#xff08;1&#xff09;文档查询 &#xff08;2&#xff09;自定义信号与内置槽函数的使用 4、信号与槽函数关联关系 5、带参数的信号与槽函数…

【软件设计师笔记】程序语言设计考点

【考证须知】IT行业高含金量的证书(传送门)&#x1f496; 【软件设计师笔记】计算机系统基础知识考点(传送门)&#x1f496; 【软件设计师笔记】操作系统考点(传送门)&#x1f496; &#x1f413; 编程语言之间的翻译形式 汇编 高级程序不能直接在计算机上执行&#xff0c;…

yolov8训练自己的关键点检测模型

参考&#xff1a; https://blog.csdn.net/weixin_38807927/article/details/135036450 标注数据集 安装labelme pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple如果报错 $ labelme 2024-01-31 03:16:20,636 [INFO ] __init__:get_config:67- Loading …

YOLOv5改进系列(29)——添加DilateFormer(MSDA)注意力机制(中科院一区顶刊|即插即用的多尺度全局注意力机制)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

面试宝典之深谈JVM

面试宝典之深谈JVM 1.为什么需要JVM&#xff0c;不要JVM可以吗&#xff1f; 1.JVM可以帮助我们屏蔽底层的操作系统 一次编译&#xff0c;到处运行 2.JVM可以运行Class文件 2.JDK&#xff0c;JRE以及JVM的关系 3.我们的编译器到底干了什么事&#xff1f; 仅仅是将我们的 .ja…

深入理解 Golang 的 crypto/elliptic:椭圆曲线密码学的实践指南

深入理解 Golang 的 crypto/elliptic&#xff1a;椭圆曲线密码学的实践指南 引言crypto/elliptic 库概览基本使用教程高级应用案例性能与安全考量结论 引言 在当今数字时代&#xff0c;数据安全和加密技术成为了信息技术领域的重中之重。特别是在网络通信和数据存储领域&#…

如何系统的自学Python?通义千问、讯飞星火、文心一言及ChatGPT的回答

如何系统的自学Python&#xff1f;来看看通义千问、讯飞星火、文心一言及ChatGPT的回答. 第一个是马老师的通义千问 系统地自学Python是一个循序渐进的过程&#xff0c;从基础语法到实践项目&#xff0c;再到专业领域的深入学习。下面是一个详细的步骤指南&#xff1a; 了解Py…

控制台npm start终止不了?

控制台npm start终止不了&#xff1f; 在开发的过程中我遇到了这样的问题&#xff0c;想结束控制台3002端口运行&#xff0c;但是ControlC不起作用&#xff0c;不管我敲多少遍&#xff0c;依旧没有任何动静&#xff1a; 再次启动的时候它又会自动启动3003端口&#xff0c;300…

Kotlin 协程:深入理解 ‘async { }‘

Kotlin 协程&#xff1a;深入理解 ‘async { }’ Kotlin 协程是一种强大的异步编程工具&#xff0c;它提供了一种简洁、易读的方式来处理并发和异步操作。在 Kotlin 协程库中&#xff0c;async {} 是一个关键的函数&#xff0c;它允许我们启动一个新的协程&#xff0c;并返回一…

【大厂AI课学习笔记】1.4 算法的进步(2)

关于感知器的兴衰。 MORE&#xff1a; 感知器的兴衰 一、感知器的发明与初期振动 在人工智能的历史长河中&#xff0c;感知器&#xff08;Perceptron&#xff09;无疑是一个里程碑式的存在。它最初由心理学家Frank Rosenblatt在1950年代提出&#xff0c;并在随后的几年中得到…

【数字电子技术课程设计】多功能数字电子钟的设计

目录 摘要 1 设计任务要求 2 设计方案及论证 2.1 任务分析 2.1.1 晶体振荡器电路 2.1.2 分频器电路 2.1.3 时间计数器电路 2.1.4 译码驱动电路 2.1.5 校时电路 2.1.6 整点报时/闹钟电路 2.2 方案比较 2.3 系统结构设计 2.4 具体电路设计 3 电路仿真测试及结…

在IT行业,拥有含金量高的证书是职业发展的关键

IT行业有哪些证书含金量高? 在IT行业&#xff0c;技能和知识是职业发展的基石。随着技术的不断进步和行业的日新月异&#xff0c;持续学习和获得相关的专业证书已经成为IT专业人士提升自己竞争力的重要手段。拥有含金量高的证书不仅能够证明个人的专业能力&#xff0c;还能帮…

京东物流基于 StarRocks 的数据分析平台建设

作者&#xff1a;京东物流 数据专家 刘敬斌 小编导读&#xff1a; 京东集团 2007 年开始自建物流&#xff0c;2017 年 4 月正式成立京东物流集团&#xff0c;截至目前&#xff0c;京东物流已经构建了一套全面的智能物流系统&#xff0c;实现服务自动化、运营数字化及决策智能化…

开源编辑器:ONLYOFFICE文档又更新了!

办公软件 ONLYOFFICE文档最新版本 8.0 现已发布&#xff1a;PDF 表单、RTL、单变量求解、图表向导、插件界面设计等更新。 什么是 ONLYOFFICE 文档 ONLYOFFICE 文档是一套功能强大的文档编辑器&#xff0c;支持编辑处理文本文档、电子表格、演示文稿、可填写的表单、PDF&#…

Java基础学习:System类和Static方法的实际使用

一、System类 1.在程序开发中&#xff0c;我们需要对这个运行的结果进行检验跟我们预判的结果是否一致&#xff0c;就会用到打印结果在控制台中显示出来使用到了System类。System类定义了一些和系统相关的属性和方法&#xff0c;它的属性和方法都是属于静态的&#xff0c;想使用…

数字孪生 三维建模方式以及细节步骤流程

对于数字孪生这个概念&#xff0c;三维建模不同行业认知都不尽相同。有的行业认为数字孪生重点在于建模&#xff0c;有的行业认为在于物联感知&#xff0c;还有部分认为是虚拟仿真。今天重点从建模角度和大家谈谈数字孪生技术常用的三维建模方式以及精细度分级。 数字孪生平台…

MySQL之数据库DQL

文章目录 数据查询DQL基本查询运算符算数运算符比较运算符逻辑运算符位运算符 排序查询聚合查询分组查询分页查询INSERT INTO SELECT语句SELECT INTO FROM语句 数据查询DQL 数据库管理系统一个重要功能就是数据查询&#xff0c;数据查询不应只是简单返回数据库中存储的数据&am…