I'm having an issue in Java calculating the current date minus a certain amount of days.
I have:
Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 25));
This is returning Tue Feb 16 09:04:18 EST 2016 when it should actually return Tue Dec 28 16:06:11 EST 2015 (25 days into the past).
What's very strange is that for any number under 25 days works completely fine:
Date pastDate = new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 24));
As in 24 days into the past returns a predictable Tue Dec 29 16:06:11 EST 2015 .
Any help would be appreciated.
With 24
days, the product remains just below the maximum possible int
value, Integer.MAX_VALUE
, which is 2,147,483,647. The 24
days product is 2,073,600,000. The 25
days product is 2,160,000,000. The result is overflow and a negative number, resulting in a date in the future.
For such values, use a long
literal for the first value (or cast it to a long
) to avoid the overflow that comes with exceeding Integer.MAX_VALUE
. Note the L
appended to 1000L
:
(1000L * 60 * 60 * 24 * 25)
This works fine because the desired constructor for Date
takes a long
.
Date arithmetic is handled more cleanly by using Calendar
s, where you can explicitly add
a negative number of days.
Also, with Java 8+, you can use Instant
and its minus
method to subtract the time.
Instant.now().minus(24, ChronoUnit.DAYS);
Do not roll your own date-time calculations. Date-time work is a surprisingly tricky business. You have already run into the common int
-versus- long
error with calculation of milliseconds. Use a decent date-time library. Fortunately Java now comes with the industry's best such library.
As mentioned in the correct Answer by rgettman , you should be using the new java.time framework built into Java 8 and later. The old date-time classes bundled with the earliest versions of Java are notoriously troublesome.
Basics of java.time… An Instant
is a moment on the timeline in UTC. Apply a time zone ( ZoneId
) to get a ZonedDateTime
.
Time zone is crucial in determining dates, as the date is not the same around the world at any one moment. A new day dawns earlier in the east.
Instant instant = Instant.now(); // In UTC.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime zdtTwentyFiveDaysAgo = zdt.minusDays( 25 );
You may want the first moment of the day for that date-time of 25 days ago rather then the current time-of-day. The first moment is not always 00:00:00.0
because of Daylight Saving Time (DST) and perhaps other anomalies. So let java.time determine the time-of-day. We have to go through LocalDate
and then back to ZonedDateTime
to get the first moment.
ZonedDateTime zdtTwentyFiveDaysAgoStart = zdtTwentyFiveDaysAgo.toLocalDate().atStartOfDay( zoneId );
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.