从今天起计算过去日期的Java将进入未来

时间:2016-01-22 21:10:26

标签: java datetime

我在Java中遇到计算当前日期减去一定天数的问题。

我有:

Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 25));

这是 Tue Feb 16 09:04:18 2016年当它实际应该返回 Tue Dec 28 16:06:11 2015 (25天进入过去)。

非常奇怪的是,25天以下的任何数字都可以完全正常运行:

Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 24));

在过去的24天内返回可预测的 Tue Dec 29 16:06:11 2015年

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:10)

24天内,产品仍然低于最大可能intInteger.MAX_VALUE,即2,147,483,647。 24天产品为2,073,600,000。 25天产品为2,160,000,000。结果是溢出和负数,导致将来出现日期。

对于此类值,请使用long字面值作为第一个值(或将其转换为long)以避免超出Integer.MAX_VALUE时出现的溢出。请注意L附加1000L

(1000L * 60 * 60 * 24 * 25)

这很好,因为desired constructor for Date takes a long

使用Calendar s可以更清晰地处理日期算术,您可以明确地add负天数。

此外,使用Java 8+,您可以使用Instant and its minus method减去时间。

Instant.now().minus(24, ChronoUnit.DAYS);

答案 1 :(得分:3)

不要滚动自己的日期时间计算。日期工作是一项令人惊讶的棘手业务。您已经遇到了常见的int - 与 - long错误,并计算了毫秒数。使用一个体面的日期时间库。幸运的是Java现在拥有业界最好的库。

java.time

the correct Answer by rgettman中所述,您应该使用Java 8及更高版本中内置的新java.time框架。与最早版本的Java捆绑在一起的旧日期时间类是众所周知的麻烦。

java.time的基础知识... Instant是UTC时间轴上的一个时刻。应用时区(ZoneId)以获得ZonedDateTime

时区对于确定日期至关重要,因为任何时刻世界各地的日期都不一样。新的一天在东部早些时候开始。

Instant instant = Instant.now(); // In UTC.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime zdtTwentyFiveDaysAgo = zdt.minusDays( 25 );

您可能想要一天中的第一个时刻,即25天前的日期时间,而不是当前的时间。由于夏令时(DST)和其他异常现象,第一时刻并不总是00:00:00.0。所以让java.time确定时间。我们必须经过LocalDate,然后返回ZonedDateTime才能获得第一时间。

ZonedDateTime zdtTwentyFiveDaysAgoStart = zdtTwentyFiveDaysAgo.toLocalDate().atStartOfDay( zoneId );