您可以使用
ChronoUnit.DAYS
(在
org.threeten.bp.temporal
包中,或者如果您使用Java 8本机类,则在
java.time.temporal
中)来计算2个
LocalDate
对象之间的天数:
if (savedDate != null && currentDate != null) {
if (ChronoUnit.DAYS.between(savedDate, currentDate) > days) {
hasExpired = true;
}
}
编辑(赏金解释后)
在这个测试中,我使用的是 threetenbp版本1.3.4
由于您希望即使用户处于不同的时区也能正常工作,因此不应该使用 LocalDate
,因为该类不能处理时区问题。
我认为最好的解决方案是使用 Instant
类。它表示一个时间点,在任何时区都是相同的(此刻,世界上每个人都处于相同的瞬间,尽管本地日期和时间可能因所在位置而异)。
实际上,Instant
总是以协调世界时(UTC)为基准,这是一种与时区无关的标准,非常适合您的情况(因为您希望进行与用户所在时区无关的计算)。
因此,您的 savedDate
和 currentDate
都必须是 Instant
类型,并且您应该计算它们之间的差异。
现在,有一个微妙的细节。您希望在3天后过期。对于我编写的代码,我做出了以下假设:
- 3天 = 72小时
- 在72小时后的1秒钟内,它就过期了
第二个假设对于我实现解决方案非常重要。我考虑以下情况:
currentDate
比 savedDate
晚不到72小时 - 未过期
currentDate
恰好在 savedDate
后72小时 - 未过期(或已过期?请参见下面的注释)
currentDate
在 savedDate
后超过72小时(即使只有一小部分时间) - 已过期
Instant
类具有纳秒精度,因此在情况3中,即使是在72小时后的1纳秒之后,我也认为它已经过期:
import org.threeten.bp.Instant;
import org.threeten.bp.temporal.ChronoUnit;
public static boolean hasDateExpired(int days, Instant savedDate, Instant currentDate) {
boolean hasExpired = false;
if (savedDate != null && currentDate != null) {
if (ChronoUnit.NANOS.between(savedDate, currentDate) > days * ChronoUnit.DAYS.getDuration().toNanos()) {
hasExpired = true;
}
}
return hasExpired;
}
请注意,我使用
ChronoUnit.DAYS.getDuration().toNanos()
来获取一天内的纳秒数。最好依赖API而不是硬编码大量容易出错的数字。
我进行了一些测试,使用相同时区和不同时区的日期。我使用了
ZonedDateTime.toInstant()
方法将日期转换为
Instant
:
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZonedDateTime;
ZoneId sp = ZoneId.of("America/Sao_Paulo");
Instant savedDate = ZonedDateTime.of(2017, 5, 22, 10, 0, 0, 0, sp).toInstant();
System.out.println(hasDateExpired(3, savedDate, ZonedDateTime.of(2017, 5, 25, 9, 59, 59, 999999999, sp).toInstant()));
System.out.println(hasDateExpired(3, savedDate, ZonedDateTime.of(2017, 5, 25, 10, 0, 0, 0, sp).toInstant()));
System.out.println(hasDateExpired(3, savedDate, ZonedDateTime.of(2017, 5, 25, 10, 0, 0, 1, sp).toInstant()));
ZoneId london = ZoneId.of("Europe/London");
System.out.println(hasDateExpired(3, savedDate, ZonedDateTime.of(2017, 5, 25, 13, 59, 59, 999999999, london).toInstant()));
System.out.println(hasDateExpired(3, savedDate, ZonedDateTime.of(2017, 5, 25, 14, 0, 0, 0, london).toInstant()));
System.out.println(hasDateExpired(3, savedDate, ZonedDateTime.of(2017, 5, 25, 14, 0, 0, 1, london).toInstant()));
注意:对于情况 2 (currentDate
恰好是 保存日期(savedDate) 后的72小时 - 未过期)——如果您希望此项过期,只需更改上面的 if
语句以使用 >=
而不是 >
:
if (ChronoUnit.NANOS.between(savedDate, currentDate) >= days * ChronoUnit.DAYS.getDuration().toNanos()) {
...
}
如果您不需要纳秒级精度,只想比较日期之间的天数,您可以按照@Ole V.V的答案中所述的方法进行操作。我相信我们的答案非常相似(虽然我不确定这些代码是否等效),但我还没有测试足够多的情况来检查它们是否在特定情况下有所不同。
org.threeten.bp
,你可以使用java.time.LocalDate
类。 - user7605325