Java8 日期与时间 API
在 Java 中,想处理日期和时间时,通常都会选用 java.util.Date
这个类进行处理。不过不知道是设计者在当时没想好还是其它原因,在 Java 1.0 中引入的这个类,大部分的 API 在 Java 1.1 中就被标记为了 Deprecated(已过时),而这些标记为已过时的接口大部分都是一些 getter 和 setter,它们被移到了 java.util.Calendar
和 java.text.DateFormat
这些类里面。这样就出现了我想操作日期和时间,结果需要同时操作好几个类,给编程带来了麻烦。除此之外,java.util.Date
本身还有设计上的缺陷。诸如月份从 0 开始啦、年份从 1900 年开始推算(JavaScript 也是这个尿性),外部可以随意更改等。为了解决这些痛点,也出现了一些第三方的工具包帮助开发者,在 Java 8 中,一组新的日期与时间 API (JSR-310)被引入进来,解决了上面的种种问题。接下来,将简要介绍这一组 API,并给出我自己的一些使用建议。
JSR-310(日期与时间 API)简介
Java 8 中引入的这一套新的 API 位于 java.base
模块,java.time
包下。官方文档对这一组 API 的描述如下:
The main API for dates, times, instants, and durations.
The classes defined here represent the principle date-time concepts, including instants, durations, dates, times, time-zones and periods. They are based on the ISO calendar system, which is the de facto world calendar following the proleptic Gregorian rules. All the classes are immutable and thread-safe.
简单地说,就是把我们能想到的所有对时间的相关操作都包含进来了。这些日期/时间/时刻/时段类的实体都是不可改变(immutable)的,对它们的任何修改都将产生一个新的对象。因此也是线程安全的。
在这个包下常用的一些类/枚举列举如下
class /enum |
描述 |
---|---|
Instant |
表示时间轴上的一个时刻。与 java.util.Date 可以通过 Date.toInstant() 和 Date.from(Instant) 进行互相转化。 |
LocalDateTime /LocalDate /LocalTime |
表示(不带时区的)日期/时间 |
DayOfWeek |
定义了一组表示星期几的常量(e.g. TUESDAY ) |
Month |
定义了一组表示月份的常量(e.g. JULY ) |
在 API 的命名上,该包下的 API 命名遵循如下规则:
of
- static factory methodparse
- static factory method focussed on parsingget
- gets the value of somethingis
- checks if something is truewith
- the immutable equivalent of a setterplus
- adds an amount to an objectminus
- subtracts an amount from an objectto
- converts this object to another typeat
- combines this object with another, such asdate.atTime(time)
另外,根据 MyBatis 文档的说明,从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API),所以用上述的日期与时间 API 也是可以用来操作数据库中的时间数据的。其它的 ORM 框架(Hibernate 等)应该也提供了对这一套 API 的支持。
对于 Android 开发者来说,印象中是直到 API Level 28 才能够使用 JSR-310 这一套 API,所以对于 Android 开发者来说,使用第三方的日期时间库可能是更妥当的选择(出于应用程序的向下兼容)
使用例子
这里举一个我在开发考试系统过程中的例子。读者也可以通过阅读这篇文章获取更加完整的 API 使用的示例。
在考生登录考试系统中,需要设定他的考试开始时间和结束时间,其中开始时间默认为现在,结束时间由开始时间加上试卷上的考试时间(以分钟为单位)得到。
考试记录的实体类的部分代码如下:
@TableName("t_exam_record")
public class ExamRecordEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 考试记录ID
*/
@TableId("id")
private Long examRecordId;
/**
* 计划开始时间
*/
@TableField("plan_start_time")
private Instant planStartTime;
/**
* 计划结束时间
*/
@TableField("plan_end_time")
private Instant planEndTime;
/**
* 实际开始时间
*/
@TableField("actual_start_time")
private Instant actualStartTime;
/**
* 实际结束时间
*/
@TableField("actual_end_time")
private Instant actualEndTime;
// 省略 getter、setter
}
其中当考生开始考试后,需要设置 planStartTime
、planEndTime
和 actualStartTime
为相应的值。如果这里使用 java.util.Date
,那么除了直接用 new
创建一个实体会比较方便以外,其它的操作就变得相当麻烦了。而如果用上新式 API,只要以下几行代码即可完成:
/**
* 考试开始,保存考试记录
* @param limitTime 考试时长(分钟为单位)
* @return 考试记录的 DTO,用于后续处理
*/
private MobilePaperDTO saveNewRecord(int limitTime) {
ExamRecordEntity entity = new ExamRecordEntity();
Instant currentTime = Instant.now();
entity.setPlanStartTime(currentTime);
entity.setActualStartTime(currentTime);
entity.setPlanEndTime(currentTime.add(limitTime, ChronoUnit.MINUTES));
// 省略其它操作
}
其中 ChronoUnit
是预先定义好的一组时间单位。由于 Instant
代表的是时间轴上的一个点,只能加减上一个“时间段”(在 java.time.temporal
包下有相关定义)。如果这里选择使用 LocalDateTime
保存日期和时间,则可直接使用 LocalDateTime.plusMinutes()
方法。Java 并不支持运算符重载,不然在某些支持运算符重载的语言(例如 Kotlin)上,这套 API 可以表现的更优雅一些。
开发建议
就我个人的使用见解来说,这部分新的 API 肯定是越早引入越好。如果是老旧系统或者和别的不熟悉这套 API 的开发者协同开发,建议直接使用 Instant
,因为这个就是官方用来取代 Date
的类,并且与 Date
间可以相互转化,之后再慢慢引入其它 API。
Java8 日期与时间 API的更多相关文章
- Java8 日期和时间API
LocalDate.LocalTime.Instant.Duration.Period 1.1使用LocalDate和LocalTime 1.1.1LocalDate的创建方式和相关方法使用示例 @T ...
- Java8系列 (六) 新的日期和时间API
概述 在Java8之前, 我们一般都是使用 SimpleDateFormat 来解析和格式化日期时间, 但它是线程不安全的. @Test public void test() { SimpleDate ...
- 详解Java8的日期和时间API
详解Java8的日期和时间API 在JDK1.0的时候,Java引入了java.util.Date来处理日期和时间:在JDK1.1的时候又引入了功能更强大的java.util.Calendar,但是C ...
- 计算机程序的思维逻辑 (95) - Java 8的日期和时间API
本节继续探讨Java 8的新特性,主要是介绍Java 8对日期和时间API的增强,关于日期和时间,我们在之前已经介绍过两节了,32节介绍了Java 1.8以前的日期和时间API,主要的类是Date和 ...
- Java编程的逻辑 (95) - Java 8的日期和时间API
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- 《Java 8 in Action》Chapter 12:新的日期和时间API
在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.同时这个类还有两个很大的缺点:年份的起始选择是1900年,月份的起始从0开始. 在Java 1.1中,Date类中的很多 ...
- Java 8 (11) 新的日期和时间API
在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.这个类只能以毫秒的精度表示时间.这个类还有很多糟糕的问题,比如年份的起始选择是1900年,月份的起始从0开始.这意味着你 ...
- java 8中新的日期和时间API
java 8中新的日期和时间API 使用LocalDate和LocalTime LocalDate的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息.另外,它也不附带任何与时区相关的信 ...
- Java8 日期和时间类
新的日期和时间API 新的日期和时间类解决了Date和Calendar类出现的问题 浅尝 LocalDate 日期类 LocalDate of = LocalDate.of(2018, 7, 13); ...
随机推荐
- 视频监控GB28181测试参考
说明: 1. 需要对前端摄像机和后端NVR.解码器.平台进行GB28181测试和开发的人员.本文档提供的一些测试细节,比如测试环境,SIP消息格式说明,SDP文本信息字段说明,GB28181测试注意 ...
- C 语言实现回调函数
优点 不需要改变调用的主函数,只需添加命令和相应函数. #include "stdio.h" #include "stdlib.h" #include &quo ...
- JMX——以可视化形式管理与监控正在运行中的Java程序
简单理解: MBean:管理的最小单元,一个MBean就是一个可以被监控的JavaBean. MBeanServer:一个池子,各个MBean都会注册到该池子中,并且该池子提供一系列的管理.监控API ...
- Java常用关键字的原理及用法
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10843135.html 一:transient 用途:Java中一个类在定义时如果实现了Serilizabl ...
- 回顾Python装饰器
函数装饰器(function decorator)可以对函数进行“标注”,给函数提供更多的特性. 在理解装饰器之前需要理解闭包(closure).Python3.0 引入了保留关键字 nonlocal ...
- Chrome调试 ---- 控制台获取元素上绑定的事件信息以及监控事件
需求场景 在前端开发中,偶尔需要验证下某个元素上到底绑定了哪些事件,以及监控某个元素上的事件触发情况. 解决方案 普通操作 之前面对这种情况,一般采取的措施就是在各个事件里写console.info, ...
- 201871010133-赵永军《面向对象程序设计(java)》第二周学习总结
201871010133-赵永军<面向对象程序设计(java)>第二周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这 ...
- P1908 逆序对-(树状数组)
https://www.luogu.org/problem/P1908 比较喜欢线段树,懒得用树状数组(只会套模板,位运算的精髓没有领悟到),一直没有记录树状数组代码,又得捡回来,趁这道题记录一下模板 ...
- PHP csv导出数据
全部导出和时间导出 html代码,全程并不需要引用什么插件 <include file="public@header"/> <link href="__ ...
- Unable to instantiate Action, xxxAction, defined for 'showBlogDetails'
(忘了截图错误信息...) 使用SSH框架配置applicationContext.xml与struts.xml之间的映射关系 解决方案:保证applicationContext.xml中注册的bea ...