IsoChronology下Java时间API间隔计算与Period可逆性问题咨询
测试场景与预期偏差
2000 CE为闰年,全年共366天;2001 CE、2002 CE为平年,均有365天。
按照逻辑推理,计算2000年1月1日至2001年1月1日的间隔天数,结果应当比2001年1月1日至2002年1月1日的间隔天数多1天,但实际观察结果与预期不符,对应的测试代码如下:
IsoChronology isoc = IsoChronology.INSTANCE; LocalDate date1; LocalDate date2; Period period; // 计算2000年1月1日到2001年1月1日的间隔 date1 = isoc.dateYearDay(2000, 1); date2 = isoc.dateYearDay(2001, 1); period = Period.between(date1, date2); assertTrue(isoc.isLeapYear(2000L)); assertFalse(isoc.isLeapYear(2001L)); assertEquals("2000-01-01", date1.toString()); assertEquals("2001-01-01", date2.toString()); assertEquals("P1Y", period.toString()); // 计算2001年1月1日到2002年1月1日的间隔 date1 = isoc.dateYearDay(2001, 1); date2 = isoc.dateYearDay(2002, 1); period = Period.between(date1, date2); assertFalse(isoc.isLeapYear(2001L)); assertFalse(isoc.isLeapYear(2002L)); assertEquals("2001-01-01", date1.toString()); assertEquals("2002-01-01", date2.toString()); assertEquals("P1Y", period.toString());
编辑说明
- 最初的示例采用400 CE、401 CE、402 CE作为测试年份,是因为0 CE并非真实存在的年份(公元前1年和公元1年为真实年份,公元前0年等价于公元1年,公元前1年等价于公元0年)。
- 后续将示例年份调整为2000 CE、2001 CE、2002 CE,以适配非延伸性格里高利历的年份计算规则,同时移除了无关信息。
Period.toString()方法会在天数字段非0时输出天数值,例如Period.of(1 /* 年 */, 0 /* 月 */, 1 /* 天 */)的输出结果为P1Y1D。按照这个规则,原本预期两个跨年间隔的Period计算结果应当存在差异,但实际二者的输出结果均为P1Y。
补充验证说明
根据ISO历法与Period的计算规则,2001年1月28日叠加1个月零1天后得到2001年3月1日,但将该日期反向减去1个月零1天后得到的是2001年1月31日,最终结果比初始日期晚了3天;而在闰年场景下执行相同操作,最终结果会与初始日期完全一致。
对应的验证代码如下:
IsoChronology chronology = IsoChronology.INSTANCE; Period oneMonthOneDay = Period.of(0, 1, 1); Temporal january28th2001 = chronology.date(2001, 1, 28); Temporal march1st2001 = oneMonthOneDay.addTo(january28th2001); Temporal january31th2001 = oneMonthOneDay.subtractFrom(march1st2001); Assert.assertEquals("2001-01-28", january28th2001.toString()); Assert.assertEquals("2001-03-01", march1st2001.toString()); Assert.assertEquals("2001-01-31", january31th2001.toString()); Temporal january28th2004 = chronology.date(2004, 1, 28); Temporal february29th2004 = oneMonthOneDay.addTo(january28th2004); Temporal january28th2004Again = oneMonthOneDay.subtractFrom(february29th2004); Assert.assertEquals("2004-01-28", january28th2004.toString()); Assert.assertEquals("2004-02-29", february29th2004.toString()); Assert.assertEquals("2004-01-28", january28th2004Again.toString());
内容的提问来源于stack exchange,提问作者Gzorg
相关产品推荐
相关产品推荐

