Java 以十进制年数表示的时间段
Java Time period in decimal number of years
如果我计算 java.time
中 2 LocalDate
之间的差异,使用:
Period p = Period.between(testDate, today);
然后我得到一个包含年数、月数、天数的输出,如:
Days = 9
Months = 6
Years = 18
有谁知道一种将其表示为十进制类型值的简洁方法(即,上面的值约为 18.5...
)?
我会避免使用句点,而只是计算天数的差异:
float years = testDate1.until(today, ChronoUnit.DAYS) / 365.2425f;
请不要这样做。
将两个日期之间的差异表示为 'number of years' 乘数是有问题的,因为两个日期之间一年的平均长度取决于您比较的日期。这很容易出错,而且想出所有必要的测试用例来证明你做对了要困难得多。
大多数程序员不应该手动执行 date/time 计算。你几乎 保证 会弄错。说真的,有 so many ways things can go horribly wrong。地球上只有少数程序员能完全理解所涉及的许多微妙之处。你问这个问题就证明你不是他们中的一员,没关系——我也不是。你和我们绝大多数人一样,应该依靠一个坚实的 Date/Time API 喜欢 java.util.time
.
如果你真的需要一个单一的数值,那么我能想到的最安全的选择是使用天数,因为 LocalDate
API 可以为您计算该数字:
long differenceInDays = testDate.until(today, ChronoUnit.DAYS)
请注意,此差异仅对用于生成它的两个日期有效。往返转换很简单:
LocalDate today = testDate.plus(differenceInDays, ChronoUnit.DAYS)
不要 尝试手动将 Period
包含年、月和日组成部分转换为整数天数。正确答案取决于所涉及的日期,这就是为什么我们要让 LocalDate
API 为我们计算。
当精度不重要时
根据您的评论,精度对您来说不是问题,因为您只想显示某人的年龄,精确到四分之一左右。您并不是要表示 精确 的时间差异;只是一个近似值,有相当大的误差范围。您也不需要能够执行任何往返计算。这大大改变了事情。
像@VGR 这样的近似值对于这些目的来说应该绰绰有余:'number of years' 应该精确到 3 天以内(< 0.01 年),除非人们开始生活数十万年,在这种情况下你可以切换到 double
;).
@Oleg 的方法也很有效,并且会给你整个季度的日期差异,你可以将其除以 4
以转换为年份。这可能是最容易获得正确结果的解决方案,因为您不需要对结果进行舍入或截断。我认为这是最接近 java.util.time
的直接解决方案。 Java 时间 API(通常 date/time APIs)是为 正确性 设计的:它们会给你整个单位,但由于浮点类型中涉及的固有错误,它们通常会避免为您提供小数近似值(也有例外,例如 .NET 的 System.TimeSpan
)。
但是,如果您的目标是向人类用户显示某人的年龄,并且您希望比整年更精确,我认为 18 years, 9 months
(或像 18 yr, 9 mo
这样的缩写形式)更好选择比 18.75 years
.
您在其中一条评论中提到,如果您需要当前季度,则需要季度年精度,您可以使用 IsoFields.QUARTER_YEARS:
double yearAndQuarter = testDate.until(today, IsoFields.QUARTER_YEARS) / 4.0;
这样您将真正使用时间 api,始终获得正确的结果,并且 @Mike 不必厌恶任何事情。
如果我计算 java.time
中 2 LocalDate
之间的差异,使用:
Period p = Period.between(testDate, today);
然后我得到一个包含年数、月数、天数的输出,如:
Days = 9
Months = 6
Years = 18
有谁知道一种将其表示为十进制类型值的简洁方法(即,上面的值约为 18.5...
)?
我会避免使用句点,而只是计算天数的差异:
float years = testDate1.until(today, ChronoUnit.DAYS) / 365.2425f;
请不要这样做。
将两个日期之间的差异表示为 'number of years' 乘数是有问题的,因为两个日期之间一年的平均长度取决于您比较的日期。这很容易出错,而且想出所有必要的测试用例来证明你做对了要困难得多。
大多数程序员不应该手动执行 date/time 计算。你几乎 保证 会弄错。说真的,有 so many ways things can go horribly wrong。地球上只有少数程序员能完全理解所涉及的许多微妙之处。你问这个问题就证明你不是他们中的一员,没关系——我也不是。你和我们绝大多数人一样,应该依靠一个坚实的 Date/Time API 喜欢 java.util.time
.
如果你真的需要一个单一的数值,那么我能想到的最安全的选择是使用天数,因为 LocalDate
API 可以为您计算该数字:
long differenceInDays = testDate.until(today, ChronoUnit.DAYS)
请注意,此差异仅对用于生成它的两个日期有效。往返转换很简单:
LocalDate today = testDate.plus(differenceInDays, ChronoUnit.DAYS)
不要 尝试手动将 Period
包含年、月和日组成部分转换为整数天数。正确答案取决于所涉及的日期,这就是为什么我们要让 LocalDate
API 为我们计算。
当精度不重要时
根据您的评论,精度对您来说不是问题,因为您只想显示某人的年龄,精确到四分之一左右。您并不是要表示 精确 的时间差异;只是一个近似值,有相当大的误差范围。您也不需要能够执行任何往返计算。这大大改变了事情。
像@VGR 这样的近似值对于这些目的来说应该绰绰有余:'number of years' 应该精确到 3 天以内(< 0.01 年),除非人们开始生活数十万年,在这种情况下你可以切换到 double
;).
@Oleg 的方法也很有效,并且会给你整个季度的日期差异,你可以将其除以 4
以转换为年份。这可能是最容易获得正确结果的解决方案,因为您不需要对结果进行舍入或截断。我认为这是最接近 java.util.time
的直接解决方案。 Java 时间 API(通常 date/time APIs)是为 正确性 设计的:它们会给你整个单位,但由于浮点类型中涉及的固有错误,它们通常会避免为您提供小数近似值(也有例外,例如 .NET 的 System.TimeSpan
)。
但是,如果您的目标是向人类用户显示某人的年龄,并且您希望比整年更精确,我认为 18 years, 9 months
(或像 18 yr, 9 mo
这样的缩写形式)更好选择比 18.75 years
.
您在其中一条评论中提到,如果您需要当前季度,则需要季度年精度,您可以使用 IsoFields.QUARTER_YEARS:
double yearAndQuarter = testDate.until(today, IsoFields.QUARTER_YEARS) / 4.0;
这样您将真正使用时间 api,始终获得正确的结果,并且 @Mike 不必厌恶任何事情。