为什么 Java.Time.Year 被任意限制为小于其原始限制?
Why is Java.Time.Year arbitrarily limited to less than its primitive limits?
Java.Time.Year 的 Java 8 文档页面声明支持的最小和最大年份分别为 -999,999,999 和 999,999,999。
Field Summary
static int
MAX_VALUE
The maximum supported year, '+999,999,999'.
static int
MIN_VALUE
The minimum supported year, '-999,999,999'.
然而,存储年份值的原始类型变量是一个int,它应该能够存储在-2,147,483,648和2,147,483,647之间。
/**
* The year being represented.
*/
private final int year;
为什么会有这些任意限制?
使用 999,999,999 的原因与代码中解析实现的任何具体问题无关。
它很可能已被选中,因为它是任何由 1 到 9 位数字组成的数字的最大值。我们不能用 INT 将完整的年份集存储到 10 位数字,因为 9,999,999,999(坦率地说,另外 79% 的可能的 10 位数字)不能存储在整数中。重要的是要注意,格式化程序本身可以无缝支持最多 64 位的单个数字,并且仅使用 MIN/MAX 进行错误检查。如果 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 的值实际上被正确解析,但超出了 [= 可接受的值36=].
Text '+9876543210-10-31' could not be parsed: Invalid value for Year (valid values -999999999 - 999999999): 9876543210
DateTimeFormatterBuilder中的所有内容最多支持 64 个数字,一次解析一个数字。所有这些值都被安全地解析为 BigIntegers,并在索引向右移动时小心地乘以 10,完成后被转换并存储在由字段名称和 longs 组成的解析上下文中,即使字段 Months 和 Days 可以清楚地存储作为整数。这些稍后会转换回其关联的基元。
实际上,DateTimeFormatterBuilder 绝对可以使用 2,147,483,647
作为有效的 min/max 年份而不会中断。
实际上,"Java accepts any year value up to 9 digits" 的描述提出了一个具体的障碍,在将两年相加时不会出现整数溢出或混淆,并减少了关于为什么 2,100,000,000 年有效的任何潜在的黑盒混淆但是 2,200,000,000 次中断。
Java.Time.Year 的 Java 8 文档页面声明支持的最小和最大年份分别为 -999,999,999 和 999,999,999。
Field Summary
static int
MAX_VALUE
The maximum supported year, '+999,999,999'.
static int
MIN_VALUE
The minimum supported year, '-999,999,999'.
然而,存储年份值的原始类型变量是一个int,它应该能够存储在-2,147,483,648和2,147,483,647之间。
/**
* The year being represented.
*/
private final int year;
为什么会有这些任意限制?
使用 999,999,999 的原因与代码中解析实现的任何具体问题无关。
它很可能已被选中,因为它是任何由 1 到 9 位数字组成的数字的最大值。我们不能用 INT 将完整的年份集存储到 10 位数字,因为 9,999,999,999(坦率地说,另外 79% 的可能的 10 位数字)不能存储在整数中。重要的是要注意,格式化程序本身可以无缝支持最多 64 位的单个数字,并且仅使用 MIN/MAX 进行错误检查。如果 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 的值实际上被正确解析,但超出了 [= 可接受的值36=].
Text '+9876543210-10-31' could not be parsed: Invalid value for Year (valid values -999999999 - 999999999): 9876543210
DateTimeFormatterBuilder中的所有内容最多支持 64 个数字,一次解析一个数字。所有这些值都被安全地解析为 BigIntegers,并在索引向右移动时小心地乘以 10,完成后被转换并存储在由字段名称和 longs 组成的解析上下文中,即使字段 Months 和 Days 可以清楚地存储作为整数。这些稍后会转换回其关联的基元。
实际上,DateTimeFormatterBuilder 绝对可以使用 2,147,483,647
作为有效的 min/max 年份而不会中断。
实际上,"Java accepts any year value up to 9 digits" 的描述提出了一个具体的障碍,在将两年相加时不会出现整数溢出或混淆,并减少了关于为什么 2,100,000,000 年有效的任何潜在的黑盒混淆但是 2,200,000,000 次中断。