IsoChronology 闰年的天数
Number of days in leap years with IsoChronology
公元 2000 年是闰年,有 366 天。
2001 CE 和 2002 CE 没有闰年并且有 355 天。
逻辑上,如果我问公元 2000 年 1 月 1 日到 2001 年 1 月 1 日之间的天数,我应该比公元 2001 年 1 月 1 日到 2002 年 1 月 1 日之间多一天。
这不是我观察到的,请参阅下面的代码。
IsoChronology isoc = IsoChronology.INSTANCE;
LocalDate date1;
LocalDate date2;
Period period;
// Between January 1st, 0 CE and January 1st, 1 CE
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());
// Between January 1st, 1 CE and January 1st, 2 CE
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 BCE 和 1 CE 是真实的,但 0 BCE = 1 CE 和 1 BCE = 0 CE) .
编辑
将示例修改为使用 2000 CE、2001 CE 和 2002 CE 以使用(非预测)公历中的年份。
另外删除了不相关的信息。
编辑
Period.toString()
包括它们不为 0 的日子。Period.of(1 /* year /, 0 / month /, 1 / days */)
呈现为 P1Y1D
,因此我希望其中一个示例与另一个示例不同。
补充
根据ISO年表和期间,2001年1月28日之后的一个月零一天是2001年3月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());
技术上没有错。在 2000-01-01 和 2001-01-01 之间,是“1 年”(“P1Y”)的时间段。在 2001-01-01 和 2002-01-01 之间,也是“1 年”(“P1Y”)的时间段。 无处 是说 365 还是 366 天。您实际上无法从 period
中获得数字 365 或 366。
你不是在问这里的两个日期之间有多少天:
Period.between(date1, date2)
你问的是经期。
一个Period
是年月日的数字,你正好得到了“1年0月0日”的周期作为输出。
请注意,周期计算与您在数学中习惯的计算有很大不同。向 2 月 1 日添加“1 个月”会增加 28 或 29 天,但向 3 月 1 日添加“1 个月”会增加 30 天。这也意味着将“1 个月”添加到一个日期 10 次可能会得到与一次性添加“10 个月”不同的结果。
您可能想知道为什么 Period.between
不提供日期之间的天数,而只是说“1 年”。首先,请注意“1 年”和“365 天”是截然不同的时期。向 2020-01-01 添加“1 年”将为您提供 2021-01-01,但向 2020-01-01 添加“365 天”将为您提供 2020-12-31。
如果 Period.between
返回的是“365 天”或“366 天”,您将无法,例如轻松要求用户输入两个日期,并继续以该间隔输出日期。考虑:
public void iterateDatesAtRegularInterval(LocalDate date1, LocalDate date2) {
Period p = Period.between(date1, date2);
LocalDate current = date2;
while (some end condition) {
current = current.plus(p);
System.out.println(current);
}
}
如果 Period.between
返回的是“365 天”或“366 天”,而我恰好过了 2020-01-01 和 2021-01-01(366 天),则此方法接下来会输出将是 2022-01-02,IMO 对大多数人来说是非常意外的。
Period.between
基本上会选择最大的单位,因为如果您正在进行周期计算,这很可能对您最有用。
如果您想要 365/366 天的结果,请不要使用 Period
。使用类似:
assertEquals(365L, ChronoUnit.DAYS.between(date1, date2))
公元 2000 年是闰年,有 366 天。 2001 CE 和 2002 CE 没有闰年并且有 355 天。
逻辑上,如果我问公元 2000 年 1 月 1 日到 2001 年 1 月 1 日之间的天数,我应该比公元 2001 年 1 月 1 日到 2002 年 1 月 1 日之间多一天。
这不是我观察到的,请参阅下面的代码。
IsoChronology isoc = IsoChronology.INSTANCE;
LocalDate date1;
LocalDate date2;
Period period;
// Between January 1st, 0 CE and January 1st, 1 CE
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());
// Between January 1st, 1 CE and January 1st, 2 CE
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 BCE 和 1 CE 是真实的,但 0 BCE = 1 CE 和 1 BCE = 0 CE) .
编辑
将示例修改为使用 2000 CE、2001 CE 和 2002 CE 以使用(非预测)公历中的年份。
另外删除了不相关的信息。
编辑
Period.toString()
包括它们不为 0 的日子。Period.of(1 /* year /, 0 / month /, 1 / days */)
呈现为 P1Y1D
,因此我希望其中一个示例与另一个示例不同。
补充
根据ISO年表和期间,2001年1月28日之后的一个月零一天是2001年3月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());
技术上没有错。在 2000-01-01 和 2001-01-01 之间,是“1 年”(“P1Y”)的时间段。在 2001-01-01 和 2002-01-01 之间,也是“1 年”(“P1Y”)的时间段。 无处 是说 365 还是 366 天。您实际上无法从 period
中获得数字 365 或 366。
你不是在问这里的两个日期之间有多少天:
Period.between(date1, date2)
你问的是经期。
一个Period
是年月日的数字,你正好得到了“1年0月0日”的周期作为输出。
请注意,周期计算与您在数学中习惯的计算有很大不同。向 2 月 1 日添加“1 个月”会增加 28 或 29 天,但向 3 月 1 日添加“1 个月”会增加 30 天。这也意味着将“1 个月”添加到一个日期 10 次可能会得到与一次性添加“10 个月”不同的结果。
您可能想知道为什么 Period.between
不提供日期之间的天数,而只是说“1 年”。首先,请注意“1 年”和“365 天”是截然不同的时期。向 2020-01-01 添加“1 年”将为您提供 2021-01-01,但向 2020-01-01 添加“365 天”将为您提供 2020-12-31。
如果 Period.between
返回的是“365 天”或“366 天”,您将无法,例如轻松要求用户输入两个日期,并继续以该间隔输出日期。考虑:
public void iterateDatesAtRegularInterval(LocalDate date1, LocalDate date2) {
Period p = Period.between(date1, date2);
LocalDate current = date2;
while (some end condition) {
current = current.plus(p);
System.out.println(current);
}
}
如果 Period.between
返回的是“365 天”或“366 天”,而我恰好过了 2020-01-01 和 2021-01-01(366 天),则此方法接下来会输出将是 2022-01-02,IMO 对大多数人来说是非常意外的。
Period.between
基本上会选择最大的单位,因为如果您正在进行周期计算,这很可能对您最有用。
如果您想要 365/366 天的结果,请不要使用 Period
。使用类似:
assertEquals(365L, ChronoUnit.DAYS.between(date1, date2))