JSR-310中两个不同的基于周的年定义的动机是什么?

Men*_*ild 14 java iso8601 java-8 java-time

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

IsoFields.WEEK_BASED_YEAR

WeekFields.ISO.weekBasedYear()

ISO-8601定义了除其他两种日期之外的所谓周日期,即通常的日历日期(包括年,月和日)和顺序日期(包括年和日) ).星期日的格式为YYYY-'W'ww-e.w代表一周的年份,e代表数字ISO-星期几.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
Run Code Online (Sandbox Code Playgroud)

虽然我非常了解第二种变化,但我很惊讶看到第一次约会的不同结果是在其类名中使用"官方"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));
Run Code Online (Sandbox Code Playgroud)

输出是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));
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

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

Jod*_*hen 8

这是一个漏洞,IsoFields因为这个方法未经测试(对不起).在正确实施之间IsoFields和之间应该存在非常小的可观察差异WeekFields.ISO.

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

注意,测试显示获得该字段很好,该bug只影响with/ adjustInto方法WEEK_BASED_YEAR.该单元WEEK_BASED_YEARS受到影响,因为通过重新使用损坏在内部实施添加WEEK_BASED_YEAR.

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

  • 谢谢你的澄清.还有一个问题:你说"非常小的可观察差异"究竟是什么意思?应该有区别吗?我仍然想知道为什么有两个类`IsoFields`(类'IsoFields`中与周相关的字段)可以被视为类'WeekFields`的ISO-case的专用周字段. (2认同)