You can’t. Sorry. Or more precisely: you can if you know a time zone and a start time (or end time). A day may have a length of 23, 24 or 25 hours or some other length. So there isn’t any sure-fire formula for converting from milliseconds to days. So while you can safely rely on 1000 milliseconds in a second, 60 seconds in a minute (reservation below) and 60 minutes in an hour, the conversion to days needs more context in order to be sure and accurate.
Reservation: In real life a minute is occasionally 61 seconds because of a leap second. Not in Java. Java always counts a minute as 60 seconds because common computer clocks don’t know leap seconds. Common operating systems and Java itself do know not only summer time (DST) but also many other timeline anomalies that cause a day to be shorter or longer than 24 hours.
To demonstrate. I am writing this on March 29, 2021, the day after my time zone, Europe/Copenhagen, and the rest of the EU switched to summer time.
ZoneId myTimeZone = ZoneId.of("Europe/Copenhagen");
ZonedDateTime now = ZonedDateTime.now(myTimeZone);
ZonedDateTime twoDaysAgo = now.minusDays(2);
ZonedDateTime inTwoDays = now.plusDays(2);
System.out.println(ChronoUnit.MILLIS.between(twoDaysAgo, now));
System.out.println(ChronoUnit.MILLIS.between(now, inTwoDays));
Output:
169200000
172800000
So how many milliseconds are in two days depends on which two days you mean. And in which time zone.
So what to do?
If for your purpose you can safely define a day as 24 hours always, for example because your days are counted in UTC or your users are fine with the inaccuracy, use either Duration
or TimeUnit
. Since Java 9 the Duration
class will additionally tell you how many hours, minutes and seconds there are in addition to the whole days. See the answer by Arvind Kumar Avinash. For the TimeUnit
enum see the answers by whaley and Dev Parzival. In any case the good news is that it doesn’t matter if you suck at math because the math is taken care of for you.
If you know a time zone and a starting point, use ZonedDateTime
and ChronoUnit.DAYS
. In this case too the math is taken care of for you.
ZonedDateTime start = LocalDate.of(2021, Month.MARCH, 28).atStartOfDay(myTimeZone);
long millisToConvert = 170_000_000;
ZonedDateTime end = start.plus(millisToConvert, ChronoUnit.MILLIS);
long days = ChronoUnit.DAYS.between(start, end);
System.out.format("%d days%n", days);
2 days
If you additionally want the hours, minutes and seconds:
Duration remainingTime = Duration.between(start.plusDays(days), end);
System.out.format(" - and an additional %s hours %d minutes %d seconds%n",
remainingTime.toHours(),
remainingTime.toMinutesPart(),
remainingTime.toSecondsPart());
- and an additional 0 hours 13 minutes 20 seconds
If instead you had got an endpoint, subtract your milliseconds from the endpoint using the minus
method (instead of the plus
method used in the above code) to get the start point.
Under no circumstances do the math yourself as in the question and in the currently accepted answer. It’s error-prone and results in code that is hard to read. And if your reader sucks at math, he or she can spend much precious developer time trying to verify that you have done it correctly. Leave the math to proven library methods, and it will be much easier for your reader to trust that your code is correct.