Java calculating past date from today goes to the future

I have a problem in Java calculating the current date minus a certain number of days.

I have:

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

It returns on Tue February 16, 09:04:18 EST 2016, when it should really return Tuesday December 28, 16:06:11 EST 2015 (25 days in the past).

It is very strange that for any number under the age of 25 days it works perfectly fine:

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

As with the 24 days in the past, the predictable Tue appears on December 29, 16:06:11 EST 2015.

Any help would be appreciated.

+5
source share
2 answers

At 24 days, the product remains slightly below the maximum possible value of int , Integer.MAX_VALUE , which is 2,147,483,647. The product of 24 days is 2,073,600,000. The product of 25 days is Integer.MAX_VALUE . The result is an overflow and a negative number, which leads to to a date in the future.

For such values, use the long literal for the first value (or drop it to long ) to avoid overflow that exceeds the value of Integer.MAX_VALUE . Note the L added to 1000L :

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

This works great because the desired constructor for Date takes long .

Date arithmetic is handled more cleanly using Calendar s, where you can explicitly add negative number of days.

In addition, with Java 8+, you can use Instant and its minus method to subtract time.

 Instant.now().minus(24, ChronoUnit.DAYS); 
+10
source

Do not do your own time calculations. Working with a date is an amazingly complex business. You have already encountered a common error int -versus- long with the calculation of milliseconds. Use a decent time library. Fortunately, Java now comes with the industry's best library.

java.time

As rgettman's correct answer already mentioned, you should use the new java.time framework built into Java 8 and later. Older date and time classes associated with the earliest versions of Java are notoriously unpleasant.

The basics of java.time ... Instant is the moment on the timeline in UTC. Apply the time zone ( ZoneId ) to get the ZonedDateTime .

The time zone is critical for determining dates, since the date is not the same worldwide at any time. A new day is coming 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 need the first moment of the day for this date 25 days ago, and not at the current time of the day. The first point is not always 00:00:00.0 due to daylight saving time (DST) and possibly other anomalies. Therefore, let java.time determine the time of day. We have to go through LocalDate and then go back to ZonedDateTime to get the first moment.

 ZonedDateTime zdtTwentyFiveDaysAgoStart = zdtTwentyFiveDaysAgo.toLocalDate().atStartOfDay( zoneId ); 
+2
source

Source: https://habr.com/ru/post/1241278/


All Articles