14

这些是包中的两个字段java.time.temporal

IsoFields.WEEK_BASED_YEAR

WeekFields.ISO.weekBasedYear()

ISO-8601 定义了除其他两种日期外的所谓周日期,即通常的日历日期(由年、月和日组成)和序数日期(由年和年组成) )。星期日期以 YYYY-'W'ww-e 格式定义。w 代表一年中的第几周,e 代表数字 ISO-day-of-week。Y 代表基于周的年,与日历年相同,但在日历年的开始或结束时除外,因为基于周的年与最终可以在上一年开始的周周期绑定。有两个规则对于理解星期日期是如何形成的很重要:

  1. 星期总是从星期一开始。
  2. 日历年的第一周是至少包含四天的一周。

乍一看,两个 JSR-310 字段似乎是相同的,因为 ISO-8601 只提到了一种基于周的年份。但是等等,惊喜。让我们考虑以下代码示例:

LocalDate date1 = 
  LocalDate.of(2000, 2, 29).with(IsoFields.WEEK_BASED_YEAR, 2014);
System.out.println("IsoFields-Test: " + date1); // output: 2014-03-01

LocalDate date2 = 
  LocalDate.of(2000, 2, 29).with(WeekFields.ISO.weekBasedYear(), 2014);
System.out.println("WeekFields-Test: " + date2); // output: 2014-02-25

虽然我非常了解第二个变体,但我真的很惊讶看到第一次约会的不同结果,它在其类名中使用了“官方”ISO-8601-reference。解释计算结果:

日期 2000-02-29 对应于 ISO-weekdate-notation 中的 2000-W09-2 而 2014-02-25 对应于 2014-W09-2保留星期和星期几。到目前为止一切顺利。较小字段的这种保留特性类似于如何更改日历年的规则(在大多数情况下,应该保持日历日期中的月份和日期不变)。

但是 2014-03-01 的结果是什么?在这里,算法只是简单地将相应的星期日期添加了四天,以考虑“日期”字段中的差异(29 对 25)。我没有找到这种行为的任何来源或官方文档。有人知道我们在哪里可以找到这两个领域之间差异的理由吗?有关算法行为的任何可用文档?

更新:

现在我尝试用这个表达式来测试新 API 的自洽性,以便找出两个字段中哪一个得到更好的支持:

System.out.println(
  "14 week-based-years later = "
  + LocalDate.of(2000, 2, 29).plus(14, IsoFields.WEEK_BASED_YEARS));

输出是 2014-03-01 类似于所描述的情况IsoFields.WEEK_BASED_YEAR,尽管我仍然发现结果 2014-02-25 (=2014-W09-2) 更合乎逻辑。IsoFields由于到目前为止在类中也发现了这个时间单元,因此行为在类中是自洽的IsoFields。看起来像一个未记录且不直观的“功能”。

我正在使用版本:java.runtime.version=1.8.0-b132

更多测试:

LocalDate d = LocalDate.of(2014, 3, 1); // 2014-W09-6
System.out.println(
  "week-of-year in 2014-03-01: " 
  + d.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
System.out.println(
  "day-of-week in 2014-03-01: " 
  + d.get(ChronoField.DAY_OF_WEEK));

LocalDate later = d.plus(14, IsoFields.WEEK_BASED_YEARS); // 2028-03-02 = 2028-W09-4
System.out.println(
  "14 week-based-years later = " 
  + later);
System.out.println(
  "week-of-year in " + later + ": " 
  + later.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
System.out.println(
  "day-of-week in " + later + ": " 
  + later.get(ChronoField.DAY_OF_WEEK));

输出:

week-of-year in 2014-03-01: 9
day-of-week in 2014-03-01: 6
14 week-based-years later = 2028-03-02
week-of-year in 2028-03-02: 9
day-of-week in 2028-03-02: 4

我不承认任何明确的规则。在添加 14 个基于周的年份时,既不保留星期几,也不保留月份中的日期。所以这是一个额外的问题:背后的规则是IsoFields.WEEK_BASED_YEARS什么?也许 JSR-310-team 可以启发我们?

4

1 回答 1

8

这是一个错误,IsoFields因为此方法未经测试(对此感到抱歉),因此设法通过。IsoFields正确实施之间和WeekFields.ISO正确实施时应该几乎没有可观察到的差异。

查看最终将通过系统运行并修复的错误报告和补丁。

请注意,测试表明获取该字段很好,该错误with仅影响adjustInto. WEEK_BASED_YEAR该单元WEEK_BASED_YEARS受到影响,因为添加是通过重用损坏的WEEK_BASED_YEAR.

2014-08-28 更新:这是 8u20 中修复的 14 个 java.time 错误之一

于 2014-04-12T14:05:04.373 回答