Java8 日期与时间 API

时间:2022-09-24 14:28:19

在 Java 中,想处理日期和时间时,通常都会选用 java.util.Date 这个类进行处理。不过不知道是设计者在当时没想好还是其它原因,在 Java 1.0 中引入的这个类,大部分的 API 在 Java 1.1 中就被标记为了 Deprecated(已过时),而这些标记为已过时的接口大部分都是一些 getter 和 setter,它们被移到了 java.util.Calendarjava.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 method
  • parse - static factory method focussed on parsing
  • get - gets the value of something
  • is - checks if something is true
  • with - the immutable equivalent of a setter
  • plus - adds an amount to an object
  • minus - subtracts an amount from an object
  • to - converts this object to another type
  • at - combines this object with another, such as date.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
}

其中当考生开始考试后,需要设置 planStartTimeplanEndTimeactualStartTime 为相应的值。如果这里使用 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的更多相关文章

  1. Java8 日期和时间API

    LocalDate.LocalTime.Instant.Duration.Period 1.1使用LocalDate和LocalTime 1.1.1LocalDate的创建方式和相关方法使用示例 @T ...

  2. Java8系列 (六) 新的日期和时间API

    概述 在Java8之前, 我们一般都是使用 SimpleDateFormat 来解析和格式化日期时间, 但它是线程不安全的. @Test public void test() { SimpleDate ...

  3. 详解Java8的日期和时间API

    详解Java8的日期和时间API 在JDK1.0的时候,Java引入了java.util.Date来处理日期和时间:在JDK1.1的时候又引入了功能更强大的java.util.Calendar,但是C ...

  4. 计算机程序的思维逻辑 (95) - Java 8的日期和时间API

    ​本节继续探讨Java 8的新特性,主要是介绍Java 8对日期和时间API的增强,关于日期和时间,我们在之前已经介绍过两节了,32节介绍了Java 1.8以前的日期和时间API,主要的类是Date和 ...

  5. Java编程的逻辑 (95) - Java 8的日期和时间API

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  6. 《Java 8 in Action》Chapter 12:新的日期和时间API

    在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.同时这个类还有两个很大的缺点:年份的起始选择是1900年,月份的起始从0开始. 在Java 1.1中,Date类中的很多 ...

  7. Java 8 &lpar;11&rpar; 新的日期和时间API

    在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.这个类只能以毫秒的精度表示时间.这个类还有很多糟糕的问题,比如年份的起始选择是1900年,月份的起始从0开始.这意味着你 ...

  8. java 8中新的日期和时间API

    java 8中新的日期和时间API 使用LocalDate和LocalTime LocalDate的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息.另外,它也不附带任何与时区相关的信 ...

  9. Java8 日期和时间类

    新的日期和时间API 新的日期和时间类解决了Date和Calendar类出现的问题 浅尝 LocalDate 日期类 LocalDate of = LocalDate.of(2018, 7, 13); ...

随机推荐

  1. win10休眠选项在哪里设置&quest;如何设置&quest;

    本人以前安装的Win7也是碰到这个问题 http://www.jb51.net/os/win10/373383.html 查询.打开休眠命令 1.右键开始菜单,选择命令提示符(管理员) 或 win+R ...

  2. Elasticsearch基础概念理解

    熟悉ES中的几个关键概念: 节点(Node):一个elasticsearch运行的实例,其实就是一个java进程.一般情况下,一台机器运行在一台机器上. 集群(Cluster): 好几个有相同集群名称 ...

  3. servlet登录

    package com.lxr.servlet; import java.io.IOException; import java.io.PrintWriter; import java.sql.Pre ...

  4. 贪心-hdu-1789-Doing Homework again

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1789 题目意思: 有n个作业,每个作业有一个截止日期,每个作业如果超过截止日期完成的时候有一个惩罚值 ...

  5. Github-Client(ANDROID)开源之旅(四&rpar; ------ 简介Roboguice

    Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC),Guice非常小而且快.Guice是类型安全的,它能够对构造函数,属性,方法(包含任意个参数 ...

  6. ural1424 Minibus

    Minibus Time limit: 1.0 secondMemory limit: 64 MB Background Minibus driver Sergey A. Greedson has b ...

  7. 《Kubernetes权威指南》——网络原理

    1 Kubernetes网络模型 基本原则:每个Pod都拥有一个独立IP,而且假定所有Pod都在一个可以直接连通的.扁平的网络空间中. 基于基本原则,用户不需要额外考虑如何建立Pod之间的连接,也不需 ...

  8. dubbo-文档

    Srping版Dubbo集成中文地址:https://dubbo.gitbooks.io/dubbo-user-book/content/preface/background.html SpringB ...

  9. python&lowbar;docx制作word文档详细使用说明【转】

      目前网上对这一个库的介绍得很少,很零散,所以很多功能我是尽量参考其官网,但是官网上面很多功能目前只有说明文档,而代码并还没有及时更新,以至于按照官网上面做了,python却报错.比如:自定义表格的 ...

  10. HTML5 canvas绘制arcTo、translate和rotate的画法探索

      arcTo(x1,y1,x2,y2,radius) ; 还要加上moveTo的点(x0,y0) ; 第一步:找到切点 过点 (x1,y1), (x0,y0)引射线与点(x1,y1),(x2,y2) ...