java 8 新特性 日期和时间的使用姿势

背景

在java1.0的时候,引入了java.util.Date类,但是糟糕的设计被人吐槽,随即在java1.1的时候引入了java.util.Calendar类,但是很不幸,Calendar类设计也有类似的问题,而且由于java版本需要兼容之前的版本,致使java.util.Date和java.util.Calendar类同时存在,导致很多人非常困惑。基于以上原因java在JSR 310提供了新的日期和时间API ,提供了非常丰富的时间和日期。

名词解释:JSRJava Specification Requests(Java规范请求),由JCP成员向委员会提交的Java发展议案,经过一系列流程后,如果通过最终会体现在未来的Java中。最终的JSR提供了一个参考实现,它是源代码形式的技术的免费实现,以及用于验证API规范的技术兼容性工具包

java.util.Date、java.util.Calendar API缺陷

  • 名称让人误解:java.util.Date并不表示日期,他表示时间的一个瞬间,并且精度为秒。

  • 不是final类:可以被继承,并且java.sql.Date继承了java.util.Date,虽然全限定类名不一致,但是类的名称一致,容易用错。

  • 可读性差:

    Date date = new Date(1945, 7, 2, 12, 30, 0);
    System.out.println(date.toString());// Sat Aug 02 12:30:00 CEST 3845
    
  • 可变和线程不安全:日期/时间类型是自然值,可以通过不可变类型建模,但是实际上Date是可变的(通过setTime()),而且Date和Calendar都是线程不安全的。

    不可变类由于其状态无法更改而具有固有的线程安全性。但是,Date和Calendar都是可变的,这要求程序员明确考虑克隆和线程化。此外,DateTimeFormat中缺乏线程安全性尚未广为人知,并且已成为导致许多难以追踪线程问题的原因。

  • 建模类型少:除了Java SE在日期时间上存在的类问题之外,它还没有用于建模其他概念的类。非时区日期或时间,持续时间,期间和间隔在Java SE中没有类表示形式。结果,开发人员经常使用int表示持续时间,而javadoc指定了单位。

    缺乏全面的日期和时间模型也导致许多常见的操作比应有的棘手。例如,计算两个日期之间的天数是当前特别困难的问题。

  • 不支持国际化。

综上,其实java.util.Date和java.util.Calendar API还有很多缺陷,这里就不一一的列举了。

这里扩展下:其中java.util.Calendar一个典型的bug,从而导致某些用户无法输入正确的出生日期。这是由Calendar类引起的,夏季仅允许夏令时增加一小时,而从历史上看,第二次世界大战时的夏令时增加了两小时。尽管此错误已得到修复,但如果将来某个国家选择在夏季引入夏时制,并增加三个小时,那么Calendar类将再次被打破。JDK-4945385 : java.util.GregorianCalendar.getMaximum(ZONE_OFFSET) works wrong

java 8 日期和时间API

简介

由于原有的日期和时间(Date and Time)API不能满足开发者的要求且存在问题,所以java 8 中提供了新的日期和时间API。并且设计的类有线程安全、不可变、实用性强等特性,弥补之前设计时间和日期的缺陷。

新的API由三个核心思想驱动:

  • 不可变值类。java.util.SimpleDateFormatJava中 现有格式器(例如)的严重缺陷之一是它们不是线程安全的。
  • 域驱动的设计。 新的API使用紧密表示日期和时间的不同用例的类对其字段进行了非常精确的建模。这种对域驱动设计的重视在清晰度和易理解性方面提供了长期利益,但是当从以前的API移植到Java SE 8时,您可能需要考虑应用程序的域日期模型。
  • 按时间顺序分隔。 新的API使人们可以使用不同的“非ISO-8601”日历系统,例如日本或泰国使用的日历系统。

Java 8 中的时间和日期API大部分借鉴了Joda-Time项目。并且提供了新的包:java.time.*,新的API提供了日期(dates)、时间(times)、瞬时时间(instants)、持续时间(durations)等。

java 8 日期和时间类解释

Clock: 时钟,获取当地时区日期、时间等
Duration: 基于时间线的时间,比如:34.5秒
Instant: 时间戳,代表时间线上的一个瞬时点,精确到纳秒级
LocalDate: 表示日期,比如:2007-12-03
LocalDateTime: 表示日期-时间,比如:2007-12-03T10:15:30
LocalTime: 表示时间,比如:10:15:30
MonthDay: 月-日,比如: --12-03
OffsetDateTime: 带有偏移量的日期-时间,比如:2007-12-03T10:15:30+01:00
OffsetTime: 带有偏移量的时间,比如:10:15:30+01:00
Period: 基于日期的时间段,比如:2年,3月和4天
Year: 年,比如:2007
YearMonth: 年-月,比如:2007-12
ZonedDateTime: 带有时区的日期-时间,比如:2007-12-03T10:15:30+01:00 Europe/Paris
ZoneId: 时区id,比如:Europe/Paris
ZoneOffset: 从Greenwich/UTC时区的偏移量,比如: +02:00
DayOfWeek: 枚举,day-of-week,比如:Tuesday
Month: month-of-year,比如:July

#java 8 日期和时间使用

说明:java 8 日期和时间的api,里边所涉及的类的方法,大家可以在这个网址方法使用的例子

输入方法签名,就可以找到
image-20191127073819425.png
例子很详细
image-20191127073924542.png

一张图来说明LocalDate、LocalTime、LocalDateTime、ZoneId、ZonedDatetTime之间的关系
模块功能 (1).png

Instant

Instant:从人的角度来看,我们习惯于星期几、几号、几点等这样的方式来理解日期和时间,但是对于机器来说不是以这样方式,从计算机的角度来看,建模时间最自然的格式是表示一个持续时间段上某个点的单一大整数型。这也是新的java.time.Instant类对时间建模的方式,基于1970-01-01T00:00:00Z(UTC时区1970年1月1日午夜时分),Instant是不可变类和线程安全,相比于System.currentTimeMillis()方法只精确到毫秒,而Instant是精确到纳秒级别。

// 获取当前时间戳 单位秒 
long nowSecond = Instant.now().getEpochSecond();
// 获取当前时间戳 单位毫秒 代替System.currentTimeMillis()
long epochMilli = Instant.now().toEpochMilli();
// 判断一个时间戳是否在另一个之前 值为false;当然还有isBefor()方法。
boolean isAfter = Instant.now().minusSeconds(10).isAfter(Instant.now());
// 构建时间戳 基于1970-01-01T00:00:00Z,可以就行纳秒级别的调整
// 向前调整了一秒,纳秒分片在0~999_999_999之间
Instant.of(3,-1000_000_000);
//还有很多方法,具体见api

LocalDate

LocalDate:LocalDate是一个不变的日期-时间对象代表了一个日期,通常被视为year-month-day。其他日期字段,如day-of-year,day-of-week,week-of-year也可以访问。例如“2nd October 2007”可以存储在一个LocalDate。这个类不存储或代表一个时间和时区。相反,它是一个描述的日期,如用于生日。它不能代表一个即时的时间线上没有额外的信息,比如一个偏移量或时区。

// 获取当前日期  ==> 2019-11-25
LocalDate today = LocalDate.now();
// 根据年月日构建日期  12就是12月份,不像之前的日期类型,11代表12月份  ==> 2019-11-29 
LocalDate ofDate = LocalDate.of(2019, 11, 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部