Java8新特性时间日期库DateTime API及示例详解

Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理。同样的,如果你现在依旧在项目中使用传统Date、Calendar和SimpleDateFormat等API来处理日期相关操作,这篇文章你一定不要错过。来刷新你的知识库吧!

背景

Java对日期、日历及时间的处理一直以来都饱受诟病,比如java.util.Date和java.util.Calendar类易用性差,不支持时区,非线程安全;还有用于格式化日期的类DateFormat也是非线程安全的等问题。

Java8引入的新的一系列API,对时间日期的处理提供了更好的支持,清楚的定义了时间日期的一些概念,比如说,瞬时时间(Instant),持续时间(duration),日期(date),时间(time),时区(time-zone)以及时间段(Period)。

同时,借鉴了Joda库的一些优点,比如将人和机器对时间日期的理解区分开的。

简介

新的时间日期API核心位于java.time内,另外也在java.time.chrono,java.time.format,java.time.temporal和java.time.zone有相关的API,但使用频次较少。

Java8常用的日期和时间类包含LocalDate、LocalTime、Instant、Duration、Period、LocalDateTime以及ZonedDateTime等。

  • LocalDate:不包含时间的日期,比如2019-10-14。可以用来存储生日,周年纪念日,入职日期等。
  • LocalTime:与LocalDate想对照,它是不包含日期的时间。
  • LocalDateTime:包含了日期及时间,没有偏移信息(时区)。
  • ZonedDateTime:包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
  • Instant:时间戳,与System.currentTimeMillis()类似。
  • Duration:表示一个时间段。
  • Period:用来表示以年月日来衡量一个时间段。

另外,还有新的日期解析格式化类DateTimeFormatter。

学习最佳的途径就是去实践它,现在我们示例的形式来讲每个知识点进行讲解。

LocalDate-如何获得日期

LocalDate类内只包含日期,不包含具体时间。只需要表示日期而不包含时间,就可以使用它。

// 只获取日期
LocalDate today = LocalDate.now();
System.out.println(today);

int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();

System.out.printf("Year : %d Month : %d day : %d \t %n", year, month, day);

同时,还可以通过LocalDate获取日期是月份的第几天、周的第几天,月份的天数,是否为闰年等。看下面的代码是不是非常方便。

LocalDate today = LocalDate.now();
// 月份中的第几天
int dayOfMonth = today.getDayOfMonth();
// 一周的第几天
DayOfWeek dayOfWeek = today.getDayOfWeek();
// 月份的天数
int length = today.lengthOfMonth();
// 是否为闰年
boolean leapYear = today.isLeapYear();

上面通过now获取LocalDate对象,也可以通过静态方法of()或parse创建任意一个日期。再也不用像之前一样年只能从1900年开始,月必须从0开始等。

LocalDate oneDay = LocalDate.of(2019,10,1);
System.out.println(oneDay);

LocalDate parseDay = LocalDate.parse("2019-10-01");
System.out.println(parseDay);

打印结果:2019-10-01。

LocalDate重写了equals方法,让日期的比较也变得简单了。

// 定义任意日期
LocalDate oneDay = LocalDate.of(2019, 10, 1);
System.out.println(oneDay);

// 定义任意比较
LocalDate anyDay = LocalDate.of(2019, 10, 1);
System.out.println(oneDay.equals(anyDay));

同时,针对日期还可延伸出MonthDay或YearMonth类,顾名思义,只包含月天或年月。同样适用于equals方法来比较。

另外使用before和after可以比较两个日期前后时间。

boolean notBefore = LocalDate.parse("2019-10-01").isBefore(LocalDate.parse("2019-10-02"));
boolean isAfter = LocalDate.parse("2019-10-01").isAfter(LocalDate.parse("2019-10-02"));

对日期进行前一天后一天或前一个月的加减也变得十分方便。

LocalDate tomorrowDay = LocalDate.now().plusDays(1);
LocalDate nextMonth = LocalDate.now().plusMonths(1);

还有,我们在实战的时候往往要获取某一天的开始时间和当天所在月的第一天等。

LocalDate.now().atStartOfDay();
LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());

LocalTime-如何获取时间

LocalTime和LocalDate类似,区别在于LocalDate不包含具体时间,而LocalTime包含具体时间。同样可以使用now或of方法来获得对象。

LocalTime localTime = LocalTime.now();
LocalTime oneTime = LocalTime.of(10,10,10);

LocalDate类似它也拥有parse、isBefore、获取时间单元等方法,就不再赘述。

需要注意的是,LocalTime获得的时间格式为:11:41:58.904。也就是,HH:mm:ss.nnn,这里nnn是纳秒。

还有一个在实战中查询日期区间时我们经常定义的“23:59:59.99”常量再也不用自己定义了。

// 23:59:59.999999999
LocalTime maxTime = LocalTime.MAX;
// 00:00
LocalTime minTime = LocalTime.MIN;

LocalDateTime-日期和时间的组合

LocalDateTime表示日期和时间组合。可以通过of()方法直接创建,也可以调用LocalDate的atTime()方法或LocalTime的atDate()方法将LocalDate或LocalTime合并成一个LocalDateTime。

创建时间示例:

LocalDateTime now = LocalDateTime.now();

LocalDateTime oneTime = LocalDateTime.of(2019,10,14,10,12,12);

// 拼接日期
LocalTime.now().atDate(LocalDate.now());

LocalDateTime与LocalDate和LocalTime之间可以相互转化。其他日期增减等操作与上面的类似。

Instant-获取时间戳

Instant用于一个时间戳,与System.currentTimeMillis()类似,但Instant可以精确到纳秒(Nano-Second)。

Instant除了可以使用now()方法创建,还可以通过ofEpochSecond方法创建。

Instant now = Instant.now();

Instant.ofEpochSecond(365 * 24 * 60, 100);

其中ofEpochSecond第一个参数表示秒,第二个参数表示纳秒。整体表示:从1970-01-01 00:00:00开始后的365天100纳秒的时间点。

Duration-获取时间段

Duration的内部实现与Instant类似,但Duration表示时间段,通过between方法创建。

LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
Duration duration = Duration.between(from, to);

// 区间统计换算
// 总天数
long days = duration.toDays();
// 小时数
long hours = duration.toHours();
// 分钟数
long minutes = duration.toMinutes();
// 秒数
long seconds = duration.getSeconds();
// 毫秒数
long milliSeconds = duration.toMillis();
// 纳秒数
long nanoSeconds = duration.toNanos();

Duration对象还可以通过of()方法创建,该方法参数为时间段长度和时间单位。

// 7天
Duration duration1 = Duration.of(7, ChronoUnit.DAYS);
// 60秒
Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);

Period-获取日期段

Period与Duration类似,获取一个时间段,只不过单位为年月日,也可以通过of方法和between方法创建,between方法接收的参数为LocalDate。

Period period = Period.of(1, 10, 25);

Period period1 = Period.between(LocalDate.now(), LocalDate.now().plusYears(1));

ZonedDateTime-创建时区时间

ZonedDateTime类,用于处理带时区的日期和时间。ZoneId表示不同的时区。大约有40不同的时区。

获取所有时区集合:

Set allZoneIds = ZoneId.getAvailableZoneIds();

创建时区:

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

把LocalDateTime转换成特定的时区:

ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), zoneId);

另外和时区一起使用的类是OffsetDateTime类,OffsetDateTime是不变的,表示date-time偏移,存储所有日期和时间字段,精确至纳秒,从UTC/Greenwich计算偏移。

时间日期格式化

Java8对日期的格式化操作非常简单,首先看到上面的类大多都提供了parse方法,可以直接通过解析字符串得到对应的对象。

而日期和时间的格式化可通过LocalDateTime的format方法进行格式化。

LocalDateTime dateTime = LocalDateTime.now();
String str = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
System.out.println(str);
str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(str);

可以使用DateTimeFormatter预置的格式,也可以通过DateTimeFormatter.ofPattern方法来指定格式。

关键点回顾

Java8中关于时间日期的API有以下关键点:

  • 提供了javax.time.ZoneId用来处理时区。
  • 提供了LocalDate与LocalTime类。
  • 时间与日期API中的所有类都是线程安全的。
  • 明确定义了基本的时间与日期概念。
  • 核心API:Instant、LocalDate、LocalTime、LocalDateTime、ZonedDateTime。
  • DateTimeFormatter类用于在Java中进行日期的格式化与解析。

好了,关于Java8新特性的时间日期功能就将到这里,用起来是不是简单明快多了,赶紧在项目中练练手吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • mybatis如何使用Java8的日期LocalDate和LocalDateTime详解

    前言 相信大家应该都知道,在实体Entity里面,可以使用java.sql.Date.java.sql.Timestamp.java.util.Date来映射到数据库的date.timestamp.datetime等字段 但是,java.sql.Date.java.sql.Timestamp.java.util.Date这些类都不好用,很多方法都过时了. Java8里面新出来了一些API,LocalDate.LocalTime.LocalDateTime 非常好用 默认的情况下,在mybatis

  • java8 LocalDate LocalDateTime等时间类用法实例分析

    本文实例讲述了java8 LocalDate LocalDateTime等时间类用法.分享给大家供大家参考,具体如下: 这篇文章主要是java8中新的Date和Time API的实战.新的Date和Time类是Java开发者社区千呼万唤始出来的.Java8 之前存在的Date类一直都受人诟病,很多人都会选择使用第三方的date库joda-time.Java8中的date和time api是jodatime的作者参与开发的,实现了JSR310的全部内容.这些新的api都在包java.time下.

  • JDBC中使用Java8的日期LocalDate和LocalDateTime操作mysql、postgresql

    前言 相信大家应该都知道,在实体Entity里面,可以使用java.sql.Date.java.sql.Timestamp.java.util.Date来映射到数据库的date.timestamp.datetime等字段 但是,java.sql.Date.java.sql.Timestamp.java.util.Date这些类都不好用,很多方法都过时了. Java8里面新出来了一些API,LocalDate.LocalTime.LocalDateTime 非常好用 如果想要在JDBC中,使用Ja

  • Java8新特性时间日期库DateTime API及示例详解

    Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API来处理日期相关操作,这篇文章你一定不要错过.来刷新你的知识库吧! 背景 Java对日期.日历及时间的处理一直以来都饱受诟病,比如java.util.Date和java.util.Calendar类易用性差,不支持时区,非线程安全:还有用于格式化日期的类DateFormat也是非线程安全的等问题. J

  • java8新特性之日期时间API

    jdk8之前 一.java.lang.System long times = System.currentTimeMillis(); //返回的是当前时间与1970年1月1月1日0分0秒之间以毫秒为单位的时间差 //称为时间戳 System.out.println(times); 二.java.util.Date And java.sql.Date 将java.util.Date 对象转换为java.sql.Date对象: //将java.util.Date 对象转换为java.sql.Date

  • Java8 新特性之日期时间对象及一些其他特性

    日期时间对象 关于日期时间的操作可以分为两种: 转换:与字符串的互相转换,与时间戳的互相转换 计算:计算两个时间点之间的间隔.时间点与时间段的计算(计算下周N.下个月D日.去年M月D日等等) Java8 提供了三个类:LocalDate.LocalTime.LocalDateTime,它们的形式如 2020-01-01.12:30:00.2020-01-01 12:30:00 创建对象 获取类对象的方法非常非常简单 LocalDate now = LocalDate.now(); LocalDa

  • 详解Java8 新特性之日期API

    Java 8 在包java.time下包含了一组全新的时间日期API.下面的例子展示了这组新API里最重要的一些部分: 1.Clock 时钟 Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数.某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象. Clock clock = Clock.systemDefaultZone();

  • Java 8新的时间日期库的20个使用示例

    原文:http://it.deepinmind.com/java/2015/03/17/20-examples-of-date-and-time-api-from-Java8.html 除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学习如何使用Java 8的这套API.Java对日期,日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDa

  • Go编程库Sync.Pool用法示例详解

    目录 场景 用法 创建 GET & PUT 优化 Log 函数 性能测试 场景 go 如果频繁地创建.销毁对象(比如 http 服务的 json 对象,日志内容等),会对 GC 造成压力.比如下面的 Log 函数,在高并发情况下,需要频繁地创建和销毁 buffer. func Log(w io.Writer, key, val string) { b := new(bytes.Buffer) // 按一定的格式打印日志,这一段不是重点 b.WriteString(time.Now().UTC()

  • JS的时间格式化和时间戳转换函数示例详解

    JS的时间格式化和时间戳转换函数 //格式化时间 function dateFormat(fmt,date){ var o = { "M+" : date.getMonth()+1, //月份 "d+" : date.getDate(), //日 "h+" : date.getHours(), //小时 "m+" : date.getMinutes(), //分 "s+" : date.getSeconds

  • Gin与Mysql实现简单Restful风格API实战示例详解

    目录 It works main.go 编译运行 数据库 CURD 增删改查 增 查 查询列表 Query 查询单条记录 QueryRow 改 删 组织代码 封装模型方法 Handler函数 组织项目 数据库处理 数据model封装 handler 路由 分组路由 app入口 总结 我们已经了解了Golang的Gin框架.对于Webservice服务,restful风格几乎一统天下.Gin也天然的支持restful.下面就使用gin写一个简单的服务,麻雀虽小,五脏俱全.我们先以一个单文件开始,然

  • Golang官方限流器库实现限流示例详解

    目录 前言 例子 实现 小结 前言 在翻Golang官方库的过程中,发现一个有趣的库golang.org/x/time ,里面只有一个类rate,研究了一下发现它是一个限流器,实现了很多的功能,当然它的核心原理并不复杂,也就是令牌桶算法. 令牌桶算法的原理是:令牌桶会不断地把令牌添加到桶里,而请求会从桶中获取令牌,只有拥有令牌地请求才能被接受.因为桶中可以提前保留一些令牌,所以它允许一定地突发流量通过. 例子 下面是限流算法常见的写法,首先判断是否有令牌,如果有就通过,否则直接失败. packa

  • Go1.18新特性工作区模糊测试及泛型的使用详解

    目录 前言 Go工作区模式(Go Workspace Mode) 现实的情况 多仓库同时开发 多个新仓库开始开发 工作区模式是什么 推荐的使用方法 使用时的注意点 Go模糊测试(Go Fuzzing Test) 为什么Golang要支持模糊测试 模糊测试是什么 Golang的模糊测试如何使用 最简单的实践例子 提供自定义语料 使用时的注意点 Go的泛型 类型参数(Type Parameters) 类型集合(Type Sets) 类型推导(Type Inference) 类型统一化(Type Un

随机推荐