I'm trying to get the difference of two timestamps in days, and TimeUnit is returning completely incorrect results for me.
Here is my code:
long ts = 1522242239952L;
long now = 1527274162820L;
long difference = now - ts;
int ageInDays = (int) TimeUnit.MILLISECONDS.convert(difference, TimeUnit.DAYS);
int ageInDays2 = (int) (difference/(1000 * 60 * 60 * 24));
System.out.println(ageInDays);
System.out.println(ageInDays2);
Output is:
-1756844032
58
Why is the TimeUnit calculation so incorrect ?
The other answers are correct: you were performing the opposite conversion of the one you intended.
TimeUnit.MILLISECONDS.convert(difference, TimeUnit.DAYS);
converts from days to milliseconds.But how come you got a negative number?? This is because of
int
overflow. The opposite conversion was performed correctly and yielded 434 758 135 795 200 000. This is much larger than what a 32 bitint
can hold. So when you cast toint
, the most significant bits are chopped off. By chance, bit that ended up being the sign bit of theint
was 1, meaning negative. I usually avoid making such a cast without a range check first. You may want to acquire the same habit.Math.toIntExact()
is very helpful here.How to fix: java.time
The other answers are still basically correct. Still I would like to supply a couple of suggestions.
If you consider that the time from, say, 16:04 one day to 16:04 the next day is 1 day, then you need to take time zone into account to get the correct result. For example:
In this case the result of running the code just now is also the one that you had expected:
If on the other hand you define 1 day as 24 hours no matter what the wall clock reads, here’s a way to get the age with sub-second precision. You can always convert to days afterward.
Output:
The first of the two lines says that the age is 1398 hours 52 minutes 13.994841 seconds. The second line agrees with the result from before.
The thoughts behind the two snippets can also be combined and mixed. All in all I think that
java.time
gives some possibilities that would be harder to get withTimeUnit
, and some pretty clear and self-explanatory code where you wouldn’t easily make the same mistake as in the question.Links:
java.time
.Math.toIntExact