Search code examples
javatimejava.util.datelocaldate

Different time interval util.date and DAYS.between(Localtime)


Something doesn't seem right and i just dont know how I can fix it.

I want to know the difference in days between 2 dates. Now I implemented a function, which calculates the differences from milliseconds to days for util.date objects

public long calculateNumberOfDays(Date from, Date to) {
    return (to.getTime() - from.getTime()) / (1000*60*60*24);
}

My jUnit test told me, there was an error with this function, so I rewrote it using LocalDate and the ChronoUnit.DAYS.between function. It worked like a charm.

Wanting to know what the differences between those two functions were, I wrote this little test:

for(int numberDays = 1; numberDays<10; numberDays++){
        LocalDate fromLD = LocalDate.now();
        LocalDate toLD = fromLD.plusDays(numberDays);
        Date fromD = Date.valueOf(fromLD);
        Date toD = Date.valueOf(toLD);
        long diffMS = toD.getTime() - fromD.getTime();
        double diffDays = diffMS/(1000*60*60*24);
        long numDaysDate = DAYS.between(fromLD, toLD);
        System.out.println(numberDays+" = "+diffDays+"/"+numDaysDate);
}

It resulted in the following output:

1 = 1.0/1
2 = 2.0/2
3 = 3.0/3
4 = 4.0/4
5 = 4.0/5
6 = 5.0/6
7 = 6.0/7
8 = 7.0/8
9 = 8.0/9

Can someone explain to me, how this is possible? (1-4 it works, 5-9 util.date has lost a day)


Solution

  • Dates are hard. A java Date is a date and time, so when you set it to an actual date, it means midnight on that date.

    Daylight savings time kicks in any day now (at least over here), so midnight on Monday will be 23 hours after midnight on Sunday.

    Dividing integers rounds down, so 4 days and 23 hours is 4 days

    Casting the result of an integer division to a double is too late; you need to cast either or both of the inputs:

    double diffDays = diffMS/(1000*60*60*24);
    

    4.0

    double diffDays = diffMS/(1000.0*60*60*24);
    

    4.958333...