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 bit int
can hold. So when you cast to int
, the most significant bits are chopped off. By chance, bit that ended up being the sign bit of the int
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:
ZoneId zone = ZoneId.of("Africa/Mogadishu");
ZonedDateTime birth = Instant.ofEpochMilli(ts).atZone(zone);
long ageInDays = ChronoUnit.DAYS.between(birth, ZonedDateTime.now(zone));
System.out.println(ageInDays);
In this case the result of running the code just now is also the one that you had expected:
58
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.
Instant birth = Instant.ofEpochMilli(ts);
Duration age = Duration.between(birth, Instant.now());
System.out.println(age);
System.out.println(age.toDays());
Output:
PT1398H52M13.994841S
58
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 with TimeUnit
, and some pretty clear and self-explanatory code where you wouldn’t easily make the same mistake as in the question.
Links: