java.time and ThreeTenABP
I should like to contribute the modern answer: Use java.time, the modern Java date and time API for your date work. If developing for Android API level 25 or lower, then through the backport for Android, ThreeTenABP (link at the bottom).
LocalDate eDate = LocalDate.now(ZoneId.of("Europe/Paris"));
LocalDate sDate = eDate.minusDays(127);
long daysBetween = ChronoUnit.DAYS.between(sDate, eDate);
System.out.println(daysBetween);
When I ran this code today, the output was the expected:
127
Notice that the code is not only shorter, just one line for finding the difference; it is also clearer and more natural to read. The classes Date
and Calendar
that you used are poorly designed and long outdated. I recommend you don’t use them.
What went wrong in your code?
You’ve got an int
overflow in your conversion of 127 days to milliseconds. In mathematics 127 * 24 * 3600 * 1000 equals 10 972 800 000. Since the numbers you multiply are int
s, Java performs the multiplication in int
, and the largest number an int
can hold is 2 147 483 647, far from enough for your expected result. In this situation it would have been nice if Java would have thrown an exception or in some other way have made us aware of the error. It doesn’t. It tacitly throws away the high order bits, giving us a result of -1 912 101 888. Subtracting this negative number from the current time is equivalent to adding 22 days and a few hours. This explains why you got 22. Funny that 13 answers have been posted and it seems that no one has spotted this …
Even when doing the multiplication using the long
type, it still doesn’t calculate 127 days correctly, though. If the 127 days cross a transition to or from summer time (DST), which in France is the case during 254 of the 365 days of a year, the day of the transition is not 24 hours, but either 23 or 25. Which causes an incorrect number of milliseconds.
You should always leave date math to proven library methods. Never hand code it yourself. It’s more complicated than most of us think, so the risk of doing it incorrectly is high.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
- In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
- In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
- On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from
org.threeten.bp
with subpackages.
Links