我在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年。
任何帮助都将不胜感激。
答案 0 :(得分:10)
在24
天内,产品仍然低于最大可能int
值Integer.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现在拥有业界最好的库。
如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 );