-1

I need to subtract several months of time from a java.util.Date object to get a different java.util.Date. I know that there is a simple way to do this in java 8, however this must be run on my school's server that does not support java 8. My current solution looks like this:

int numDaysToSubtract = 60;
Date curDate = new Date();

//subtract numdays * hours/day * mins/hour * secs/min * millisecs/sec
Date newDate = new Date(curDate.getTime() - (numDaysToSubtract * 24 * 3600 * 1000));

curDate is 4/12/2018 and the calculated newDate is 4/2/2018, which is clearly not 60 days before 4/12/2018.

Why isn't this working as expected?

What should I try instead?

3802400
  • 57
  • 1
  • 10
  • 2
    `System.out.println(numDaysToSubtract * 24 * 3600 * 1000);` – Oliver Charlesworth Apr 12 '18 at 19:18
  • 1
    Your question has already been answered. But just FYI in case you are not aware: "Date" is outdated (no pun intended). If you can use Java 8+ then go with "LocalDate" instead. This offers - amongst others - this method: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#minus-long-java.time.temporal.TemporalUnit- – user3237736 Apr 12 '18 at 19:39
  • By the way, days are not always 24 hours long. – Basil Bourque Apr 13 '18 at 01:11

1 Answers1

4

You have overflowed the number of milliseconds to subtract, because the product doesn't fit in a 32-bit integer, whose maximum value is about 2.1 billion (10 digits).

60 days worth of milliseconds is 5,184,000,000, over the limit. Because of the overflow, the product is calculated at 889,032,704 milliseconds, or about 10.2 days.

Either cast numDaysToSubtract as a long, or declare it to be long to begin with, to force long calculations, avoiding overflow. For me, doing that results in February 11, 2018, 60 days ago.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Or force `long` in the calculation by making `24` a long literal: `(numDaysToSubtract * 24L * 3600 * 1000)`. Now all 3 multiplications are done using `long` math. – Andreas Apr 12 '18 at 19:44
  • @Andreas Sure, that would work too. That would force the first multiplication to promote the operands to `long`. While the most important thing here is to force promotion to `long` before overflow occurs, usually I would prefer a better visual representation of the left-to-right calculation, by making the first operand `long`. – rgettman Apr 12 '18 at 19:48