为什么那些奇怪的结果会计算两个 JODA 瞬间之间的年数?
Why are those weird results calculating years between two JODA instants?
最近我偶然发现了使用 Years.between() 作为 JODA 最佳实践来计算某人年龄的提示。如以下示例所示,它通常不起作用。
DateTime y0000 = new DateTime(0000, 1, 1, 0, 0, 0, 0);
DateTime y2000 = new DateTime(2000, 1, 1, 0, 0, 0, 0);
assertEquals(2000, new Period(y0000, y2000).getYears());
assertEquals(1999, Years.yearsBetween(y0000.toInstant(), y2000.toInstant()).getYears());
assertEquals(1999, new Period(y0000.toInstant(), y2000.toInstant()).getYears());
assertEquals(2000, new Period(new DateTime(y0000),new DateTime(y2000)).getYears());
JODA 是否按设计在这里工作,或者这是 JODA 缺陷?
更新:
JODA 按设计工作。如果你真的想使用 Years.between()
那么要么使用 LocalDateTime
要么确保使用 DateTimeZone.UTC
.
来自我的评论(现转入本回答):
instant-conversion 1999 年的结果可以解释为时区数据在很久以前没有明确定义。 Joda-Time 使用第二部分的估计区域偏移(TZDB-database 中所谓的 LMT 条目)。这可能导致 0 年和 2000 年的偏移量不同,从而导致年增量递减。同样重要的是要了解时区的想法是 19 世纪的想法!所以你的代码是没有意义的;-)这里设计的阴暗面也是Joda-Time启用代码而不使时区效果可见和明确。
我现在已经使用以下代码调查了本地时区的偏移量:
System.out.println(DateTimeZone.getDefault().getOffset(y0000.toInstant()) / 1000); // 3208 s
System.out.println(DateTimeZone.getDefault().getOffset(y2000.toInstant()) / 1000); // 3600 s
结果是:您必须从 y0000 中减去第一个较小的偏移量并从 y2000 中减去较大的偏移量,因此两个时刻之间的秒差值不能等于以秒表示的 2000 年。因此年增量递减。
为了避免这种意外的增量(你显然不会考虑任何时区影响),我强烈建议使用像 LocalDateTime
这样的类型。与 DateTime
相比,此类型没有时区,并且会按照您的预期进行(当然无需转换为 Instant
)。否则,如果您关心 "exact" 物理时差(通过不同的 summer/winter-time 或偏移量的历史估计),那么预期的年份差异并不正确,即应该考虑时区偏移量。
最近我偶然发现了使用 Years.between() 作为 JODA 最佳实践来计算某人年龄的提示。如以下示例所示,它通常不起作用。
DateTime y0000 = new DateTime(0000, 1, 1, 0, 0, 0, 0);
DateTime y2000 = new DateTime(2000, 1, 1, 0, 0, 0, 0);
assertEquals(2000, new Period(y0000, y2000).getYears());
assertEquals(1999, Years.yearsBetween(y0000.toInstant(), y2000.toInstant()).getYears());
assertEquals(1999, new Period(y0000.toInstant(), y2000.toInstant()).getYears());
assertEquals(2000, new Period(new DateTime(y0000),new DateTime(y2000)).getYears());
JODA 是否按设计在这里工作,或者这是 JODA 缺陷?
更新:
JODA 按设计工作。如果你真的想使用 Years.between()
那么要么使用 LocalDateTime
要么确保使用 DateTimeZone.UTC
.
来自我的评论(现转入本回答):
instant-conversion 1999 年的结果可以解释为时区数据在很久以前没有明确定义。 Joda-Time 使用第二部分的估计区域偏移(TZDB-database 中所谓的 LMT 条目)。这可能导致 0 年和 2000 年的偏移量不同,从而导致年增量递减。同样重要的是要了解时区的想法是 19 世纪的想法!所以你的代码是没有意义的;-)这里设计的阴暗面也是Joda-Time启用代码而不使时区效果可见和明确。
我现在已经使用以下代码调查了本地时区的偏移量:
System.out.println(DateTimeZone.getDefault().getOffset(y0000.toInstant()) / 1000); // 3208 s
System.out.println(DateTimeZone.getDefault().getOffset(y2000.toInstant()) / 1000); // 3600 s
结果是:您必须从 y0000 中减去第一个较小的偏移量并从 y2000 中减去较大的偏移量,因此两个时刻之间的秒差值不能等于以秒表示的 2000 年。因此年增量递减。
为了避免这种意外的增量(你显然不会考虑任何时区影响),我强烈建议使用像 LocalDateTime
这样的类型。与 DateTime
相比,此类型没有时区,并且会按照您的预期进行(当然无需转换为 Instant
)。否则,如果您关心 "exact" 物理时差(通过不同的 summer/winter-time 或偏移量的历史估计),那么预期的年份差异并不正确,即应该考虑时区偏移量。