Module  java.base
软件包  java.time.chrono

Interface ChronoLocalDate

  • All Superinterfaces:
    Comparable<ChronoLocalDate>TemporalTemporalAccessorTemporalAdjuster
    所有已知实现类:
    HijrahDateJapaneseDateLocalDateMinguoDateThaiBuddhistDate


    public interface ChronoLocalDate
    extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate>
    一个无时间,无时间的日期,用于任意年龄,用于高级全球化用例。

    大多数应用程序应声明方法签名,字段和变量为LocalDate ,而不是此接口。

    A ChronoLocalDateChronology chronology或日历系统可插拔的日期的抽象表示。 日期由TemporalField表示的字段定义,其中大多数常见实现在ChronoField中定义。 年表定义日历系统的运行方式和标准字段的含义。

    何时使用此界面

    API的设计鼓励使用LocalDate而不是该接口,即使在应用程序需要处理多个日历系统的情况下。

    首先,这个概念似乎令人惊讶,因为全局化应用程序的自然方式可能最初似乎是抽象日历系统。 然而,如下所述,抽象日历系统通常是错误的方法,导致逻辑错误,很难找到错误。 因此,应该认为应用程序范围的架构决定选择使用此接口而不是LocalDate

    要考虑的建筑问题

    这些是在整个应用程序中使用此界面之前必须考虑的一些要点。

    1)使用这个界面的应用程序,而不是使用LocalDate ,面临着更高的错误概率。 这是因为正在使用的日历系统在开发时不知道。 错误的主要原因是开发人员将ISO日历系统日常知识的假设应用于旨在处理任意日历系统的代码。 以下部分概述了这些假设如何导致问题。减少错误风险增加的主要机制是强大的代码审查流程。 在代码生命周期中,这也应被视为维护的额外成本。

    2)此接口不强制执行不可变性。 虽然实现说明表明所有实现都必须是不可变的,但代码或类型系统中没有任何内容来执行此操作。 因此,任何声明接受ChronoLocalDate都可能被传递给一个不好或恶意编写的可变实现。

    3)使用此界面的应用程序必须考虑到时代的影响。 LocalDate屏蔽了用户从时代的概念,通过确保getYear()返回getYear()年份。 该决定确保开发人员可以将LocalDate实例视为三个字段(年,月,日和月)。 相比之下,这个界面的用户必须将日期视为包括四个领域 - 时代,年龄,月份和月份。 额外的时代领域经常被遗忘,但是在任意的日历系统中是至关重要的。 例如,在日历系统中,这个时代代表了皇帝的统治地位。 每当一个统治结束,另一个开始时,年龄将重置为一个。

    4)在两个系统之间通过日期的唯一商定的国际标准是需要ISO日历系统的ISO-8601标准。 在整个应用程序中使用此界面将不可避免地导致要求通过网络或组件边界传递日期,需要特定于应用程序的协议或格式。

    5)长期持续性,如数据库,几乎总是只接受ISO-8601日历系统(或相关的朱利安 - 格里高利)的日期。 在其他日历系统中传播日期增加了与持久性相互作用的并发症。

    6)大部分时间,通过一个ChronoLocalDate整个应用程序是不必要的,如下面最后一节所讨论的。

    虚假假设导致多日历系统代码中的错误

    如上所述,尝试在任意日历系统中使用和操纵日期时,需要考虑许多问题。 这些是一些关键问题。

    查询月份的代码,并假定该值永远不会超过31,则无效。 某些日历系统在几个月内有超过31天的时间。

    增加12个月的代码,并假设已经添加了一年是无效的。 一些日历系统有不同的月份,例如科普特人或埃塞俄比亚的13个。

    增加一个月到日期的代码,并假设年月值增加一个或换到下一年是无效的。 一些日历系统在一年中可能有几个月,例如希伯来语。

    增加一个月的代码,然后再增加一个月,并假设月日将保持接近其原始值是无效的。 一些日历系统在最长月份的长度和最短的月份的长度之间有很大差异。 例如,科普特人或埃塞俄比亚人有12个月30天,1个月5天。

    添加七天并假定一周已添加的代码无效。 一些日历系统有七个星期的时间,如法国革命派。

    假设因为date1的年份大于date2 date1年,那么date1之后的date2是无效的。 对于所有的日历系统来说,这是对于年代的无效,尤其是在每个新皇帝统治时代重新开始的日历日历系统的时候。

    将月份中的一个月和一个月中的一个作为年初的代码无效。 当月份值为1时,不是所有的日历系统开始。

    一般来说,操作日期,甚至查询日期,当日历系统在开发时是未知的时,广泛使用错误。 这就是为什么使用此界面的代码必须经过其他代码审查的原因。 这也是为什么避免这种接口类型的架构决策通常是正确的。

    使用LocalDate代替

    在整个应用程序中使用此界面的主要替代方法如下。
    • LocalDate引用日期的所有方法签名。
    • 请将用户配置文件中的年表(日历系统)存储或从用户区域设置查找年表
    • 在打印和解析期间将ISO LocalDate转换为用户的首选日历系统
    这种方法将全球化日历系统的问题视为本地化问题,并将其限制在UI层。 这种方法与java平台中的其他本地化问题保持一致。

    如上所述,在日历系统的规则可插拔的日期执行计算需要技能,不推荐。 幸运的是,在任意日历系统的日期执行计算的需求是极少数的。 例如,图书馆租借计划的商业规则极不可能允许租金为一个月,其中月份的含义取决于用户的首选日历系统。

    用于在任意日历系统中的日期进行计算的关键用例是生成逐月显示和用户交互的日历。 再次,这是一个UI问题,仅仅在UI层的几个方法中使用这个接口可能是合理的。

    在系统的任何其他部分,如果在除ISO之外的日历系统中必须操纵日期,则用例通常会指定要使用的日历系统。 例如,申请可能需要计算下一个可能需要操纵日期的伊斯兰教或希伯来节假日。 这种用例可以如下处理:

    • 从ISO LocalDate开始传递给该方法
    • 将日期转换为备用日历系统,对于此用例而言,该日历系统是已知的而不是任意的
    • 执行计算
    • 转换回LocalDate
    编写低级框架或库的开发人员也应该避免这个接口。 而应该使用两个通用接入接口之一。 使用TemporalAccessor如果需要只读访问,或使用Temporal是否需要进行读写访问。
    实现要求:
    该接口必须小心实施,以确保其他类正确运行。 可以实例化的所有实现必须是最终的,不可变的和线程安全的。 子类应尽可能可序列化。

    可以向系统添加其他日历系统。 详见Chronology

    从以下版本开始:
    1.8
    • 方法详细信息

      • from

        static ChronoLocalDate from​(TemporalAccessor temporal)
        从时间对象获取一个ChronoLocalDate的实例。

        这将基于指定的时间获取本地日期。 A TemporalAccessor表示一个任意的日期和时间信息集,该工厂转换为ChronoLocalDate一个实例。

        转换提取并结合时间对象的年表和日期。 该行为相当于使用Chronology.date(TemporalAccessor)与提取的年表。 允许实现执行优化,例如访问与相关对象相当的那些字段。

        该方法匹配功能接口TemporalQuery的签名,允许其通过方法参考ChronoLocalDate::from用作查询。

        参数
        temporal - 要转换的时间对象,不为null
        结果
        日期,不为空
        异常
        DateTimeException - 如果无法转换为 ChronoLocalDate
        另请参见:
        Chronology.date(TemporalAccessor)
      • getChronology

        Chronology getChronology​()
        获得这个日期的年表。

        Chronology代表正在使用的日历系统。 时代和其他领域在ChronoField由时间顺序定义。

        结果
        年表,不为空
      • getEra

        default Era getEra​()
        获得时代,按年表定义。

        时代在概念上是时间线上最大的一个部门。 大多数日历系统具有将时间线划分为两个时代的单个时期。 然而,有些有多个时代,比如每个领导人统治的时代。 具体含义由Chronology确定。

        所有正确实现的Era类都是单例,因此它是有效的代码写入date.getEra() == SomeChrono.ERA_NAME)

        此默认实现使用Chronology.eraOf(int)

        结果
        在这个时间适用的年代比特定时代不为零
      • isLeapYear

        default boolean isLeapYear​()
        检查年份是否是日历系统定义的闰年。

        闰年是一个比正常长的一年。 确切的意义是由年表确定的,其限制是闰年必须意味着比非闰年长一年的长度。

        此默认实现使用Chronology.isLeapYear(long)

        结果
        如果此日期在闰年,则为真,否则为false
      • lengthOfMonth

        int lengthOfMonth​()
        返回由日历系统定义的由此日期表示的月份的长度。

        这将以天为单位返回月份的长度。

        结果
        月的长度以天为单位
      • lengthOfYear

        default int lengthOfYear​()
        返回由日历系统定义的由此日期表示的年份的长度。

        这返回一年中的天数。

        默认实现使用isLeapYear()并返回365或366。

        结果
        一年中的天数
      • isSupported

        default boolean isSupported​(TemporalField field)
        检查指定的字段是否受支持。

        这将检查是否可以在此日期查询指定的字段。 如果是假,然后调用rangegetwith(TemporalField, long)方法会抛出异常。

        支持的字段集由年表定义,通常包括所有ChronoField日期字段。

        如果该字段是不是一个ChronoField ,则此方法的结果是通过调用得到TemporalField.isSupportedBy(TemporalAccessor)传递this作为参数。 字段是否受支持由字段决定。

        Specified by:
        isSupported在接口 TemporalAccessor
        参数
        field - 要检查的字段,null返回false
        结果
        如果可以查询该字段,则为true,否则为false
      • isSupported

        default boolean isSupported​(TemporalUnit unit)
        检查指定的单位是否受支持。

        这将检查是否可以从该日期添加或减去指定的单位。 如果是false,那么调用plus(long, TemporalUnit)minus方法会抛出异常。

        支持单位的集合由年表定义,通常包括除了FOREVER之外的所有ChronoUnit日期单位。

        如果该单元不是ChronoUnit ,则此方法的结果是通过调用得到TemporalUnit.isSupportedBy(Temporal)传递this作为参数。 设备是否受支持由本机决定。

        Specified by:
        isSupported在接口 Temporal
        参数
        unit - 要检查的单位,null返回false
        结果
        如果可以添加/减去单位,则为真,否则为false
      • with

        default ChronoLocalDate with​(TemporalAdjuster adjuster)
        通过进行调整,返回与该对象相同类型的调整对象。

        这将根据指定的调整器的规则调整此日期时间。 一个简单的调整器可能只是设置一个字段,如年份字段。 更复杂的调整器可能会将日期设置为该月的最后一天。 TemporalAdjusters提供了一些常见的调整。 这些包括找到“月的最后一天”和“下周三”。 调整员负责处理特殊情况,如月份和闰年的不同长度。

        一些示例代码,指示如何和为什么使用此方法:

          date = date.with(Month.JULY);        // most key classes implement TemporalAdjuster
          date = date.with(lastDayOfMonth());  // static import from Adjusters
          date = date.with(next(WEDNESDAY));   // static import from Adjusters and DayOfWeek 
        Specified by:
        with在接口 Temporal
        参数
        adjuster - 调整器使用,不为空
        结果
        具有指定调整的相同类型的对象,不为null
        异常
        DateTimeException - 如果不能进行调整
        ArithmeticException - 如果发生数字溢出
      • with

        default ChronoLocalDate with​(TemporalField field,
                                     long newValue)
        返回与该对象具有相同类型的对象,并更改指定的字段。

        这将返回一个基于该对象的新对象,其中指定字段的值已更改。 例如,在LocalDate ,这可以用于设置年,月或月。 返回的对象将具有与该对象相同的可观察类型。

        在某些情况下,更改字段尚未完全定义。 例如,如果目标对象是代表1月31日的日期,则将月份更改为2月份将不清楚。 在这种情况下,该领域负责解决结果。 通常,它将选择先前的有效日期,这将是本例中最后一个有效的二月份。

        Specified by:
        with在接口 Temporal
        参数
        field - 要在结果中设置的字段,不为null
        newValue - 结果中字段的新值
        结果
        与指定字段集相同类型的对象,不为null
        异常
        DateTimeException - 如果字段无法设置
        UnsupportedTemporalTypeException - 如果该字段不被支持
        ArithmeticException - 如果发生数字溢出
      • plus

        default ChronoLocalDate plus​(TemporalAmount amount)
        返回与此对象相同类型的对象,并添加一个金额。

        这调整这个时间,根据指定量的规则添加。 金额通常为Period但可能是实现TemporalAmount接口的任何其他类型,例如Duration

        一些示例代码,指示如何和为什么使用此方法:

          date = date.plus(period);                // add a Period instance
          date = date.plus(duration);              // add a Duration instance
          date = date.plus(workingDays(6));        // example user-written workingDays method 

        请注意,呼叫plus后跟minus不保证返回相同的日期时间。

        Specified by:
        plus在接口 Temporal
        参数
        amount - 要添加的金额,不为null
        结果
        具有指定调整的相同类型的对象,不为null
        异常
        DateTimeException - 如果不能添加
        ArithmeticException - 如果发生数字溢出
      • plus

        default ChronoLocalDate plus​(long amountToAdd,
                                     TemporalUnit unit)
        返回与此对象相同类型的对象,并添加指定的句点。

        此方法基于添加了指定句点的新对象。 例如,在LocalDate ,这可以用来添加几年,几个月或几天。 返回的对象将具有与该对象相同的可观察类型。

        在某些情况下,更改字段尚未完全定义。 例如,如果目标对象是代表1月31日的日期,则添加一个月将不清楚。 在这种情况下,该领域负责解决结果。 通常,它将选择先前的有效日期,这将是本例中最后一个有效的二月份。

        Specified by:
        plus在接口 Temporal
        参数
        amountToAdd - 要添加的指定单位的数量,可能为负数
        unit - 要添加的单位,不为null
        结果
        与指定期间相同类型的对象添加,不为空
        异常
        DateTimeException - 如果无法添加本机
        ArithmeticException - 如果发生数字溢出
      • minus

        default ChronoLocalDate minus​(TemporalAmount amount)
        返回与该对象相同类型的对象,并减去一个数量。

        这调整这个时间,根据指定量的规则减去。 金额通常为Period但可以是实现TemporalAmount接口的任何其他类型,例如Duration

        一些示例代码,指示如何和为什么使用此方法:

          date = date.minus(period);               // subtract a Period instance
          date = date.minus(duration);             // subtract a Duration instance
          date = date.minus(workingDays(6));       // example user-written workingDays method 

        请注意,呼叫plus后跟minus不保证返回相同的日期时间。

        Specified by:
        minus在接口 Temporal
        参数
        amount - 减去量,不为空
        结果
        具有指定调整的相同类型的对象,不为null
        异常
        DateTimeException - 如果不能进行减法
        ArithmeticException - 如果发生数字溢出
      • minus

        default ChronoLocalDate minus​(long amountToSubtract,
                                      TemporalUnit unit)
        返回与该对象相同类型的对象,并减去指定的时间段。

        该方法返回一个基于该对象的新对象,减去指定的时间段。 例如,在LocalDate ,这可以用来减去几年,几个月或几天的数量。 返回的对象将具有与该对象相同的可观察类型。

        在某些情况下,更改字段尚未完全定义。 例如,如果目标对象是代表3月31日的日期,则减去一个月将不清楚。 在这种情况下,该领域负责解决结果。 通常,它将选择先前的有效日期,这将是本例中最后一个有效的二月份。

        Specified by:
        minus在接口 Temporal
        参数
        amountToSubtract - 扣除指定单位的金额,可能为负数
        unit - 减去量的单位,不为空
        结果
        与指定周期相同类型的对象减去,不为空
        异常
        DateTimeException - 如果不能减去单位
        UnsupportedTemporalTypeException - 如果不支持本机
        ArithmeticException - 如果发生数字溢出
      • query

        default <R> R query​(TemporalQuery<R> query)
        使用指定的查询查询此日期。

        这使用指定的查询策略对象查询此日期。 TemporalQuery对象定义了用于获取结果的逻辑。 阅读查询的文档,以了解该方法的结果。

        该方法的结果是通过调用TemporalQuery.queryFrom(TemporalAccessor)方法在指定的查询上传递this作为参数获得的。

        Specified by:
        query在接口 TemporalAccessor
        参数类型
        R - 结果的类型
        参数
        query - 要调用的查询,不为空
        结果
        查询结果可能返回null(由查询定义)
        异常
        DateTimeException - 如果无法查询(由查询定义)
        ArithmeticException - 如果发生数字溢出(由查询定义)
      • adjustInto

        default Temporal adjustInto​(Temporal temporal)
        调整指定的时间对象与此对象的日期相同。

        这返回与日期改变为与之相同的输入的相同可观察类型的时间对象。

        该调整是相当于使用Temporal.with(TemporalField, long)通过ChronoField.EPOCH_DAY作为字段。

        在大多数情况下,通过使用Temporal.with(TemporalAdjuster)更正呼叫模式:

          // these two lines are equivalent, but the second approach is recommended
           temporal = thisLocalDate.adjustInto(temporal);
           temporal = temporal.with(thisLocalDate); 

        此实例是不可变的,不受此方法调用的影响。

        Specified by:
        adjustInto在接口 TemporalAdjuster
        参数
        temporal - 要调整的目标对象,不为空
        结果
        调整对象,不为null
        异常
        DateTimeException - 如果不能进行调整
        ArithmeticException - 如果发生数字溢出
      • until

        long until​(Temporal endExclusive,
                   TemporalUnit unit)
        根据指定的单位计算直到另一个日期的时间量。

        这个计算两个之间的时间量ChronoLocalDate在单一方面对象TemporalUnit 起点和终点为this和指定日期。 如果结束在开始之前,结果将为负数。 所述Temporal传递给此方法被转换为ChronoLocalDate使用Chronology.date(TemporalAccessor) 计算返回一个整数,表示两个日期之间的完整单位数。 例如,可以使用startDate.until(endDate, DAYS)计算两个日期之间的天startDate.until(endDate, DAYS)

        使用这种方法有两种等效的方法。 第一个是调用这个方法。 二是使用TemporalUnit.between(Temporal, Temporal)

          // these two lines are equivalent
           amount = start.until(end, MONTHS);
           amount = MONTHS.between(start, end); 
        应该根据这种做法进行选择,使代码更易读。

        该方法的计算是通过ChronoUnit实现的 单位DAYSWEEKSMONTHSYEARSDECADESCENTURIESMILLENNIAERAS应该由所有的实现支持。 其他ChronoUnit值会抛出异常。

        如果该单元不是ChronoUnit ,则此方法的结果是通过调用得到TemporalUnit.between(Temporal, Temporal)传递this作为第一个参数和转换后的输入时间作为第二个参数。

        此实例是不可变的,不受此方法调用的影响。

        Specified by:
        until在接口 Temporal
        参数
        endExclusive - 结束日期,排他,在同一年代转换为 ChronoLocalDate ,不为空
        unit - 衡量金额的单位,不为空
        结果
        此日期与结束日期之间的时间
        异常
        DateTimeException - 如果不能计算金额,或者结束时间不能转换为 ChronoLocalDate
        UnsupportedTemporalTypeException - 如果不支持本机
        ArithmeticException - 如果发生数字溢出
      • until

        ChronoPeriod until​(ChronoLocalDate endDateExclusive)
        将此日期与另一个日期之间的期间计算为ChronoPeriod

        这计算两个日期之间的期间。 所有提供的年表使用年,月和日计算周期,但是ChronoPeriod API允许使用其他单位来表示期间。

        起点和终点为this和指定日期。 如果结束在开始之前,结果将为负数。 每年,每月的负号将相同。

        计算使用此日期的年表进行。 如有必要,输入日期将被转换为匹配。

        此实例是不可变的,不受此方法调用的影响。

        参数
        endDateExclusive - 结束日期,排他,可能在任何年代,不为空
        结果
        此日期与结束日期之间的期间不为空
        异常
        DateTimeException - 如果期间无法计算
        ArithmeticException - 如果发生数字溢出
      • format

        default String format​(DateTimeFormatter formatter)
        使用指定的格式化程序格式化此日期。

        此日期将传递给格式化程序以生成一个字符串。

        默认实现必须如下所示:

          return formatter.format(this); 
        参数
        formatter - 要使用的格式化程序,不为null
        结果
        格式化的日期字符串,不为null
        异常
        DateTimeException - 打印过程中是否发生错误
      • atTime

        default ChronoLocalDateTime<?> atTime​(LocalTime localTime)
        将此日期与时间结合起来创建一个ChronoLocalDateTime

        这将在指定的时间返回从此日期形成的ChronoLocalDateTime 日期和时间的所有可能的组合都是有效的。

        参数
        localTime - 当地使用时间,不为空
        结果
        从该日期到指定时间形成的本地日期时间,不为空
      • toEpochDay

        default long toEpochDay​()
        将此日期转换为大纪元日。

        Epoch Day count是第0天为1970-01-01(ISO)的简单递增计数。 这个定义对于所有的年表都是一样的,可以进行转换。

        此默认实现查询EPOCH_DAY字段。

        结果
        大纪元日等于这个日期
      • compareTo

        default int compareTo​(ChronoLocalDate other)
        将此日期与其他日期进行比较,包括年表。

        比较首先是基于时间线日期,然后是时间顺序。 它与“等于”一致,由Comparable定义。

        例如,以下是比较器顺序:

        1. 2012-12-03 (ISO)
        2. 2012-12-04 (ISO)
        3. 2555-12-04 (ThaiBuddhist)
        4. 2012-12-05 (ISO)
        值2和#3表示时间线上相同的日期。 当两个值表示相同的日期时,比较年表ID以区分它们。 需要这一步才能使排序“与...一致”。

        如果所有被比较的日期对象都在相同的年表中,则不需要额外的时间表,只使用本地日期。 要比较两个TemporalAccessor实例的日期,包括两个不同年表中的日期,请使用ChronoField.EPOCH_DAY作为比较。

        此默认实现执行上面定义的比较。

        Specified by:
        compareTo在接口 Comparable<ChronoLocalDate>
        参数
        other - 要比较的其他日期,不为null
        结果
        比较器值为负,如果较小,则如果较大则为正
      • isAfter

        default boolean isAfter​(ChronoLocalDate other)
        检查此日期是否在忽略年表的指定日期之后。

        该方法与compareTo(java.time.chrono.ChronoLocalDate)中的比较不同之处在于,它只比较基础日期而不是年表。 这允许根据时间线位置来比较不同日历系统中的日期。 这相当于使用date1.toEpochDay() > date2.toEpochDay()

        此默认实现基于时间段执行比较。

        参数
        other - 要比较的其他日期,不为空
        结果
        如果这是在指定日期之后,则为true
      • isBefore

        default boolean isBefore​(ChronoLocalDate other)
        检查此日期是否在忽略年表前的指定日期之前。

        该方法与compareTo(java.time.chrono.ChronoLocalDate)中的比较不同之处在于,它仅比较基础日期而不是年表。 这允许根据时间线位置来比较不同日历系统中的日期。 这相当于使用date1.toEpochDay() < date2.toEpochDay()

        此默认实现基于时间段执行比较。

        参数
        other - 要比较的其他日期,不为空
        结果
        如果这是在指定日期之前,则为true
      • isEqual

        default boolean isEqual​(ChronoLocalDate other)
        检查这个日期是否等于忽略年表的指定日期。

        该方法与compareTo(java.time.chrono.ChronoLocalDate)中的比较不同之处在于,它仅比较基础日期而不是年表。 这允许根据时间线位置来比较不同日历系统中的日期。 这相当于使用date1.toEpochDay() == date2.toEpochDay()

        此默认实现基于时间段执行比较。

        参数
        other - 要比较的其他日期,不为null
        结果
        如果基础日期等于指定日期,则为true
      • equals

        boolean equals​(Object obj)
        检查这个日期是否等于另一个日期,包括年表。

        将此日期与另一个日期进行比较,确保日期和年表相同。

        要比较两个TemporalAccessor实例的日期,包括两个不同年表中的日期,请使用ChronoField.EPOCH_DAY作为比较。

        重写:
        equalsObject
        参数
        obj - 要检查的对象,null返回false
        结果
        如果这等于其他日期,则为真
        另请参见:
        Object.hashCode()HashMap
      • toString

        String toString​()
        将此日期输出为String

        输出将包括完整的本地日期。

        重写:
        toStringObject
        结果
        格式化日期,不为null