模块 java.base

包 java.time


java.time

日期、时间、瞬间和持续时间的主要 API。

此处定义的类代表主要的日期时间概念,包括瞬间、持续时间、日期、时间、时区和周期。它们基于 ISO 日历系统,即事实上的世界日历遵循 proleptic Gregorian 规则。所有的类都是不可变的和线程安全的。

每个日期时间实例都由 API 方便地提供的字段组成。对于字段的较低级别访问,请参阅 java.time.temporal 包。每个类都支持打印和解析各种日期和时间。有关自定义选项,请参阅 java.time.format 包。

java.time.chrono 包包含日历中性 API ChronoLocalDate ChronoLocalDateTime ChronoZonedDateTime Era 。这旨在供需要使用本地化日历的应用程序使用。建议应用程序跨系统边界使用此包中的 ISO-8601 日期和时间类,例如数据库或网络。日历中性 API 应保留用于与用户的交互。

日期和时间

Instant 本质上是一个数字时间戳。当前 Instant 可以从 Clock 中检索。这对于时间点的日志记录和持久化很有用,并且在过去与存储来自 System.currentTimeMillis() 的结果相关联。

LocalDate 存储没有时间的日期。这会存储日期,如“2010-12-03”,可用于存储生日。

LocalTime 存储没有日期的时间。这会存储一个时间,如“11:30”,可用于存储开始或结束时间。

LocalDateTime 存储日期和时间。这会存储日期时间,例如“2010-12-03T11:30”。

ZonedDateTime 存储带有时区的日期和时间。如果您想在考虑 ZoneId 的情况下执行准确的日期和时间计算,例如“欧洲/巴黎”,这将非常有用。在可能的情况下,建议使用没有时区的更简单的类。时区的广泛使用往往会给应用程序增加相当大的复杂性。

持续时间和期间

除了日期和时间,API 还允许存储时间段和持续时间。 Duration 是沿时间线以纳秒为单位的简单时间度量。 Period 表示以对人类有意义的单位表示的时间量,例如年或天。

附加值类型

Month 单独存储一个月。这会单独存储一年中的某个月份,例如“DECEMBER”。

DayOfWeek 单独存储星期几。这会单独存储一周中的某一天,例如“星期二”。

Year 单独存储一年。这将单独存储单个年份,例如“2010”。

YearMonth 存储没有日期或时间的年份和月份。这存储年份和月份,例如“2010-12”,可用于信用卡到期。

MonthDay 存储没有年份或时间的月份和日期。这会存储月份和日期,例如“--12-03”,并且可用于存储年度事件(如生日)而不存储年份。

OffsetTime 存储没有日期的时间和与 UTC 的偏移量。这会存储一个日期,例如“11:30+01:00”。 ZoneOffset 的格式为“+01:00”。

OffsetDateTime 存储日期和时间以及与 UTC 的偏移量。这会存储日期时间,例如“2010-12-03T11:30+01:00”。这有时会在 XML 消息和其他形式的持久性中找到,但包含的信息少于完整时区。

包装规格

除非另有说明,否则将 null 参数传递给此包中任何类或接口中的构造函数或方法将导致抛出 NullPointerException 。 Javadoc“@param”定义用于总结空行为。每个方法中都没有明确记录“@throws NullPointerException ”。

所有计算都应检查数字溢出并抛出 ArithmeticException DateTimeException

设计说明(非规范)

API 旨在尽早拒绝 null 并明确此行为。一个关键的异常是任何接受一个对象并返回一个boolean的方法,为了检查或验证的目的,通常会为 null 返回 false。

API 被设计为在主要高级 API 中合理的地方是类型安全的。因此,日期、时间和日期时间的不同概念有单独的类,还有偏移量和时区的变体。这看起来有很多类,但大多数应用程序可以从五个日期/时间类型开始。

  • Instant - 时间戳
  • LocalDate - 没有时间的日期,或任何对偏移量或时区的引用
  • LocalTime - 没有日期的时间,或任何对偏移量或时区的引用
  • LocalDateTime - 结合了日期和时间,但仍然没有任何偏移量或时区
  • ZonedDateTime - 带有时区的“完整”日期时间和与 UTC/格林威治的已解析偏移量

Instant 是最接近 java.util.Date 的等效类。 ZonedDateTime 是最接近 java.util.GregorianCalendar 的等效类。

在可能的情况下,应用程序应使用 LocalDateLocalTimeLocalDateTime 来更好地为域建模。例如,生日应该存储在代码 LocalDate 中。请记住,对 时区 的任何使用(例如“欧洲/巴黎”)都会给计算增加相当大的复杂性。许多应用程序只能使用 LocalDateLocalTimeInstant 编写,并在用户界面 (UI) 层添加时区。

基于偏移量的日期时间类型 OffsetTimeOffsetDateTime 主要用于网络协议和数据库访问。例如,大多数数据库不能自动存储像“欧洲/巴黎”这样的时区,但它们可以存储像“+02:00”这样的偏移量。

还为日期中最重要的子部分提供了类,包括 MonthDayOfWeekYearYearMonthMonthDay 。这些可用于为更复杂的日期时间概念建模。例如,YearMonth 可用于表示信用卡到期。

请注意,虽然有大量类代表日期的不同方面,但处理时间不同方面的类相对较少。遵循类型安全的逻辑结论会产生小时-分钟、小时-分钟-秒和小时-分钟-秒-纳秒类。虽然在逻辑上是纯粹的,但这不是一个实际的选择,因为由于日期和时间的组合,它会使类的数量几乎增加三倍。因此,LocalTime 用于所有时间精度,零用于表示较低的精度。

遵循完全类型安全的最终结论可能还需要为日期时间中的每个字段创建一个单独的类,例如 HourOfDay 的类和 DayOfMonth 的另一个类。尝试过这种方法,但是在Java语言中过于复杂,缺乏可用性。句号也会出现类似的问题。每个周期单位都有一个单独的类,例如 Years 的类型和 Minutes 的类型。但是,这会产生很多类和类型转换问题。因此,提供的日期时间类型集是纯粹性和实用性之间的折衷。

API 在方法数量方掩码有相对较大的表面积。这通过使用一致的方法前缀变得易于管理。

  • of - 静态工厂方法
  • parse - 专注于解析的静态工厂方法
  • get - 获取某物的值
  • is - 检查是否为真
  • with - setter 的不变等价物
  • plus - 向对象添加数量
  • minus - 从对象中减去一个数量
  • to - 将此对象转换为另一种类型
  • at - 将此对象与另一个对象组合,例如 date.atTime(time)

多个日历系统是对设计挑战的尴尬补充。第一个原则是大多数用户需要标准的 ISO 日历系统。因此,主要类仅适用于 ISO。第二个原则是大多数想要非 ISO 日历系统的人都希望它用于用户交互,因此这是一个 UI 本地化问题。因此,日期和时间对象应作为 ISO 对象保存在数据模型和持久存储中,仅与本地日历相互转换以供显示。日历系统将单独存储在用户首选项中。

然而,在一些有限的用例中,用户认为他们需要在整个应用程序的任意日历系统中存储和使用日期。这是由 ChronoLocalDate 支持的,但是在使用它之前阅读该接口的 Javadoc 中的所有相关警告至关重要。总之,需要在多个日历系统之间进行一般互操作的应用程序通常需要以与仅使用 ISO 日历的应用程序截然不同的方式编写,因此大多数应用程序应该只使用 ISO 并避免使用 ChronoLocalDate

API 还为用户可扩展性而设计,因为计算时间的方法有很多种。 field单元 API,通过 TemporalAccessor Temporal 访问,为应用程序提供了相当大的灵活性。此外,TemporalQuery TemporalAdjuster 接口提供日常功能,允许代码阅读接近业务需求:

  LocalDate customerBirthday = customer.loadBirthdayFromDatabase();
  LocalDate today = LocalDate.now();
  if (customerBirthday.equals(today)) {
   LocalDate specialOfferExpiryDate = today.plusWeeks(2).with(next(FRIDAY));
   customer.sendBirthdaySpecialOffer(specialOfferExpiryDate);
  }

 
自从:
1.8
  • 描述
    使用时区提供对当前时刻、日期和时间的访问的时钟。
    异常用于在计算日期时间时指示问题。
    星期几,例如“星期二”。
    基于时间的时间量,例如“34.5 秒”。
    时间线上的一个瞬时点。
    提供对当前时刻的访问。
    ISO-8601 日历系统中没有时区的日期,例如 2007-12-03
    ISO-8601 日历系统中没有时区的日期时间,例如 2007-12-03T10:15:30
    ISO-8601 日历系统中没有时区的时间,例如 10:15:30
    一年中的一个月,例如“七月”。
    ISO-8601 日历系统中的月日,例如 --12-03
    在 ISO-8601 日历系统中与 UTC/Greenwich 有偏移的日期时间,例如 2007-12-03T10:15:30+01:00
    与 ISO-8601 日历系统中的 UTC/Greenwich 有偏移的时间,例如 10:15:30+01:00
    ISO-8601 日历系统中基于日期的时间量,例如“2 年、3 个月和 4 天”。
    ISO-8601 日历系统中的年份,例如 2007
    ISO-8601 日历系统中的年月,例如 2007-12
    ISO-8601 日历系统中带有时区的日期时间,例如 2007-12-03T10:15:30+01:00 Europe/Paris
    时区 ID,例如 Europe/Paris
    与格林威治/UTC 的时区偏移量,例如 +02:00