【问题标题】:Why is Java.Time.Year arbitrarily limited to less than its primitive limits?为什么 Java.Time.Year 被任意限制在其原始限制以下?
【发布时间】:2018-12-11 20:17:29
【问题描述】:

Java.Time.Year 的 Java 8 文档页面指出,支持的最小和最大年份分别为 -999,999,999 和 999,999,999。

字段摘要

static intMAX_VALUE支持的最大年份,'+999,999,999'。

static intMIN_VALUE支持的最小年份,'-999,999,999'。


但是,存储年份值的原始类型变量是 int,它应该能够存储 -2,147,483,648 和 2,147,483,647 之间的值。

/**
 * The year being represented.
 */
private final int year;

为什么会有这些任意限制?

【问题讨论】:

  • 因为java.time 主要基于 ISO,并且 ISO 年份表示它“必须有一个商定的额外年份位数超过四-最少位数”,至少根据Wikipedia。解析为 9 位数字。
  • 999_999_999 的使用不是任意的,因为它包括从 -999_999_999 到 +999_999_999 的每个可能的年份,因此每个可能的年份最多 9 位都是可用的。使用 INT_MAX 时,并非所有最多 10 位数的可能年份都可用,这些年份中只有 21% 可用。
  • @Andreas 最少四位数字不是 9 位,而是四位(-9999 到 +9999)。
  • @MenoHochschild "extra year digits" 当年份存储在 int 中时,最多解析为 9 位数字,因为 int 无法存储 10 的完整范围数字。
  • @Andreas 感谢您的澄清。对我来说是一个误解(我不是以英语为母语的人)。

标签: java time limit


【解决方案1】:

使用 999,999,999 的原因与代码中解析实现的任何特定问题无关。

它很可能已被选中,因为它是由 1 到 9 位数字组成的任何数字的最大值。我们不能用 INT 将完整的年份存储到 10 位,因为 9,999,999,999(坦率地说,还有 79% 的可能的 10 位数字)不能存储在整数中。需要注意的是,格式化程序本身可以无缝支持最多 64 位的单个数字,并且仅使用 MIN/MAX 进行错误检查。如果将最小值/最大值提高到 INT_MIN 和 INT_MAX,它仍然可以正常工作。超过 INT_MAX 的值会正确抛出错误并防止任何有关整数溢出的问题,因此无需担心任何类型的解析失败。

    ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);

对于传统 ISO,年份是 4 个数字,即 0-9999,或者有一个 +/-,即对于年份 999999 的 +999999。

值得注意的是,ISO_LOCAL_DATE 格式化程序默认接受 10 位数年份,不包括 +/- 符号,因此 +9,876,543,210 的值实际上已正确解析,但超出了 MAX_YEAR 的可接受值。

Text '+9876543210-10-31' could not be parsed: Invalid value for Year (valid values -999999999 - 999999999): 9876543210

DateTimeFormatterBuilder 中的所有内容最多支持 64 位数字,一次解析一个数字。所有这些值都被安全地解析为 BigIntegers,并在索引向右移动时小心地乘以 10,完成后被转换并存储在由字段名称和 long 组成的解析上下文中,即使字段 Months 和 Days 可以清楚地存储作为整数。这些稍后会转换回它们相关的原语。

实际上,DateTimeFormatterBuilder 绝对可以使用2,147,483,647 作为有效的最小/最大年份而不会中断。

实际上,“Java 接受最多 9 位数的任何年份值”的描述提出了一个具体的障碍,即在将两年加在一起时不会出现整数溢出或混淆,并减少了任何潜在的黑盒混淆,例如为什么 2,100,000,000 年有效,而 2,200,000,000 年则停了下来。

【讨论】:

    猜你喜欢
    • 2019-02-11
    • 1970-01-01
    • 2012-08-04
    • 2014-01-05
    • 1970-01-01
    • 2019-02-15
    • 2011-12-02
    • 2021-09-25
    • 2019-10-13
    相关资源
    最近更新 更多