Java 8 Instant.range和Instant.with看起来不一致



我正在尝试为基于属性的测试生成java.time.Instant的实例,使用Temporal.range对我尝试过的几乎所有Temporal子类都非常有效-除了Instant似乎没有提供有用的最小&最大值。

这个简化的例子:

import java.time.Instant;
import java.time.temporal.ChronoField;
public class Main {
public static void main(String[] args) {
Instant.EPOCH.with(
ChronoField.INSTANT_SECONDS,
Instant.EPOCH.range(ChronoField.INSTANT_SECONDS).getMaximum()
);
}
}

抛出此异常:

Exception in thread "main" java.time.DateTimeException: Instant exceeds minimum or maximum instant
at java.time.Instant.create(Instant.java:411)
at java.time.Instant.with(Instant.java:718)
at Main.main(Main.java:6)

可运行的版本可以在这里找到

一个简单的反例是,使用LocalDate的等效代码的行为与文档中预期的完全一样,正确地处理了一个月中的可变日期:

import java.time.LocalDate;
import java.time.temporal.ChronoField;
public class Main {
public static void main (String[] args){
for(int m = 1; m <= 12; m++) {
LocalDate startOfMonth = LocalDate.of(2019, m, 1);
LocalDate endOfMonth = startOfMonth.with(
ChronoField.DAY_OF_MONTH,
startOfMonth.range(ChronoField.DAY_OF_MONTH).getMaximum());
System.out.println(
startOfMonth.toString() + " -> " + endOfMonth.toString()
);
}
}
}

此处为可运行版本

我这里有什么东西不见了吗?

ChronoField返回的范围服从IsoChronology.range,它表示:

注意,结果只描述了最小和最大有效值,重要的是不要对它们读太多。例如,范围内可能存在对字段无效的值。

实际上,IsoChronology.INSTANCE.range(ChronoField.INSTANT_SECONDS).getMaximum()返回的值是Long.MAX_value。它没有考虑Instant的限制。

实际最大值由Instant.MAX定义。

TL;DR:没有遗漏任何内容,实际上是一个错误


不幸的是,Java Bug数据库没有很好的可见性,除非您已经在那里提交了一个Bug。

在尝试这样做的过程中,我发现已经有一个针对这种不当行为的漏洞#8212895,它在一年多前(2018-10-18(被打开。

在撰写本文时,它被归类为P4(P1是最高优先级,P5是最低优先级(,所以它不太可能在短期内看到任何爱情。

相关内容

最新更新