共计 2314 个字符,预计需要花费 6 分钟才能阅读完成。
Date-Time
Java SE 8 发行版中引入的 Date-Time 包 java.time 提供了全面的日期和时间模型,是在 JSR 310:Date and Time API 下开发的,尽管 java.time 基于国际标准化组织(ISO)日历系统,但也支持常用的全球日历。
此课程介绍了使用基于 ISO 的类来表示日期和时间以及操作日期和时间值的基本原理。
概述
时间似乎是一个简单的主题,即便是便宜的手表也能提供合理准确的日期和时间,但是,通过仔细研究,你会发现微妙的复杂性和许多影响你理解时间的因素。例如,在 1 月 31 日添加一个月的结果对于闰年而言与其他年份不同,时区也增加了复杂性,例如,一个国家可能会在短时间内进出夏令时,或者一年多次进入夏令时,或者可能在某一年内完全跳过夏令时。
Date-Time API 使用 ISO-8601 中定义的日历系统作为默认日历,此日历基于公历系统,并在全球范围内用作表示日期和时间的事实标准。Date-Time API 中的核心类有 LocalDateTime、ZonedDateTime 和 OffsetDateTime 等,所有这些都使用 ISO 日历系统。如果你想使用其他日历系统,例如 Hijrah 或 Thai Buddhist,java.time.chrono 包允许你使用其中一个预定义的日历系统,或者你可以创建自己的。
Date-Time API 使用 Unicode 公共语言环境数据存储库(CLDR),这个存储库支持全世界的语言,并包含全世界最大的可用语言环境数据集合,此存储库中的信息已本地化为数百种语言。Date-Time API 还使用时区数据库(TZDB),该数据库提供了自 1970 年以来全球每个时区变化的信息,以及自引入该概念以来的主要时区的历史记录。
Date-Time 设计原则
Date-Time API 是使用几个设计原则开发的。
明确
API 中的方法定义明确,其行为清晰且预期,例如,使用 null 参数值调用 Date-Time 方法通常会触发 NullPointerException。
流畅
Date-Time API 提供了流畅的接口,使代码易于阅读,因为大多数方法不允许具有 null 值的参数并且不返回 null 值,所以可以将方法调用链接在一起,并且可以快速理解生成的代码,例如:
LocalDate today = LocalDate.now();
LocalDate payday = today.with(TemporalAdjusters.lastDayOfMonth()).minusDays(2);
不可变
Date-Time API 中的大多数类创建的对象不可变,这意味着在创建对象后,它不能被修改,要更改不可变对象的值,必须将新对象构造为原始对象的修改副本。这也意味着根据定义,Date-Time API 是线程安全的。这会影响 API,因为用于创建日期或时间对象的大多数方法都以 for、from 或 with 作为前缀,而不是构造函数,并且没有 set 方法,例如:
LocalDate dateOfBirth = LocalDate.of(2012, Month.MAY, 14);
LocalDate firstBirthday = dateOfBirth.plusYears(1);
可扩展
Date-Time API 尽可能是可扩展的,例如,你可以定义自己的时间调整器和查询,或构建自己的日历系统。
Date-Time 包
Date-Time API 由主包 java.time 和四个子包组成:
java.time
用于表示日期和时间的核心 API,它包括日期、时间、日期和时间组合、时区、时刻,持续时间和时钟的类,这些类基于 ISO-8601 中定义的日历系统,并且是不可变的和线程安全的。
java.time.chrono
用于表示除默认 ISO-8601 之外的日历系统的 API,你还可以定义自己的日历系统,本教程未详细介绍此包。
java.time.format
用于格式化和解析日期和时间的类。
java.time.temporal
扩展 API,主要用于编写框架和库,允许日期和时间类之间的互操作、查询和调整,字段(TemporalField 和 ChronoField)和单元(TemporalUnit 和 ChronoUnit)在此包中定义。
java.time.zone
支持时区、时区偏移和时区规则的类,如果使用时区,大多数开发人员只需要使用 ZonedDateTime、ZoneId 或 ZoneOffset。
方法命名约定
Date-Time API 在一组丰富的类中提供了一组丰富的方法,尽可能在类之间使方法名一致,例如,许多类提供了一个 now 方法,用于捕获与该类相关的当前时刻的日期或时间值,from 方法允许从一个类转换到另一个类。
关于方法名称前缀也有标准化,由于 Date-Time API 中的大多数类都是不可变的,因此 API 不包含 set 方法(创建后,无法更改不可变对象的值,set 方法的不可变等价是 with),下表列出了常用的前缀:
前缀
方法类型
使用
of
静态工厂
创建一个实例,其中工厂主要验证输入参数,而不是转换它们。
from
静态工厂
将输入参数转换为目标类的实例,这可能涉及从输入中丢失信息。
parse
静态工厂
解析输入字符串以生成目标类的实例。
format
实例
使用指定的格式化程序来格式化时间对象中的值以生成字符串。
get
实例
返回目标对象状态的一部分。
is
实例
查询目标对象的状态。
with
实例
返回更改了一个元素的目标对象的副本;这是 JavaBean 上 set 方法的不可变等价物。
plus
实例
返回添加时间量的目标对象的副本。
minus
实例
返回减去时间量的目标对象的副本。
to
实例
将此对象转换为另一种类型。
at
实例
将此对象与另一个对象组合。