当前位置: 首页 > 面试题库 >

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

朱宇航
2023-03-14
问题内容

这是包中的两个字段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

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

日期2000-02-29对应于ISO-weekdate-表示法中的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团队可以启发我们吗?


问题答案:

这是一个漏洞,IsoFields由于此方法未经测试(对不起),因此无法通过。正确实施之间IsoFields和之间的差异应该很小WeekFields.ISO

请参阅错误报告和补丁程序,这些报告和补丁程序最终将在整个系统中运行并得到修复。

请注意,测试表明获取该字段很好,该错误仅影响的with/
adjustInto方法WEEK_BASED_YEAR。该单元WEEK_BASED_YEARS受到影响,因为添加是通过重用损坏的元素在内部实现的WEEK_BASED_YEAR

2014
年8月28日更新:这是8u20中修复的14个java.time错误之一。



 类似资料:
  • Isofields.week_based_year WeekFields.iso.WeekBasedYear() ISO-8601定义了一个所谓的星期日期,除了其他两种日期,即通常的日历日期(由年、月和日组成)和序号日期(由年和日组成)。周日期以yyyy-'w'ww-e格式定义。w代表一年中的一周,e代表数字中的一周中的一天。Y代表以周为单位的一年,与日历年相同,但日历年的开始或结束除外,因为以周

  • 问题内容: Java 8的类有一个方法,,它使您可以从字符串A-z,a-z字母定义格式。这些例子并没有明确的区别y,今年的时代和Y,以星期为一年。它是什么? 问题答案: 与2006-W52一样,这是“年-周”样式日期的年值。如果有问题的一周跨越年份边界,则可能偏离年份值+1或-1。

  • 问题内容: 我正在将应用程序从Joda-Time迁移到Java 8 。 我遇到的一件事是使用中的图案打印基于周的年份。 根据文档 但是,当我尝试这两个时,似乎总是会返回与相同的结果。 我的测试代码: 输出: 从重要的年份(例如2000、2005、2009和2016)来看,和的输出是不同的。 在Java的时间与DateTimeFormatter基于周周的–一年模式分析中指出,这与本地化做的(如可以清

  • 编辑:好的。不幸的是,我不得不承认我对Java时间的理解存在严重缺陷,使得这个问题毫无意义。我一直认为System.currentTimeMillis()返回了当地时间。为什么?因为当你用它创建一个Date时,它只包含那个,没有引用时区,但在传递给System.out.println()时仍然打印出当地时间。我从未想过是toString()将(UTC)时间转换为当地时区。:( 我想用Java创建一

  • 我需要以-的格式输出当前日期,即使用ISO周日期,其中一周总是从周一开始,一年的第一周是1月份至少有四天的第一周(因此是1月份有第一个周四的一周)。 由于2015年12月31日为星期四,星期五至星期日,即2016年1月1日至3日,均属2015年第53周(“漫长的一年”),而2016年第一周于1月4日星期一开始。 从DateTimeFormatter规范中,我希望可以使用模式来实现这一点(是,是)。

  • 问题内容: 我想获得任何一年中的周数。即使被接受为全球通用的答案,对于日历,而实际上有几个星期。 有什么方法可以计算出来,或者有什么函数可以帮助我? 问题答案: 根据维基百科关于ISO周日期格式的文章,您可以使用以下代码进行计算。 更新: 似乎来自@Samuel的答案更好,并且没有Luca提到的错误 快速一线: