'Java Date.getTime() returns an incorrect response for 2022 April

Using Date.getTime() to calculate the number of milliseconds in a day. Google shows 86400 seconds or 86400000 milliseconds in a day.

I measure every day in April, I notice the gap between 2022-04-3 and 2022-04-4 is 90000000. Why Date.getTime() return wrong results for 2022-04-3 and 2022-04-4?

public static void intervalTest(){
  System.out.format("date today.getTime()  tomorrow.getTime()  interval \n");
  for (int i=1;i<30;i++){
    Date d1 = new Date();
    d1.setMonth(3);
    d1.setDate(i);
    d1.setHours(0);
    d1.setMinutes(0);
    d1.setSeconds(0);
    Date d2 = new Date();
    d2.setMonth(3);
    d2.setDate(i+1);
    d2.setHours(0);
    d2.setMinutes(0);
    d2.setSeconds(0);
    long d1seconds = d1.getTime();
    long d2seconds = d2.getTime();
    long diff = (d2seconds - d1seconds);

    System.out.format("2022-04-%d %d  %d  %d\n",i,d1seconds,d2seconds,diff);
  }
}

date today.getTime()  tomorrow.getTime()  interval 
2022-04-1 1648731600348  1648818000353  86400005
2022-04-2 1648818000354  1648904400354  86400000
2022-04-3 1648904400354  1648994400354  90000000 <<<<<<<<<<<<<<<<<<<<<<<<
2022-04-4 1648994400354  1649080800354  86400000
2022-04-5 1649080800355  1649167200355  86400000
2022-04-6 1649167200355  1649253600355  86400000
2022-04-7 1649253600355  1649340000355  86400000
2022-04-8 1649340000356  1649426400356  86400000
2022-04-9 1649426400356  1649512800356  86400000
2022-04-10 1649512800356  1649599200356  86400000
2022-04-11 1649599200357  1649685600357  86400000
2022-04-12 1649685600357  1649772000357  86400000
2022-04-13 1649772000357  1649858400357  86400000
2022-04-14 1649858400357  1649944800357  86400000
2022-04-15 1649944800358  1650031200358  86400000
2022-04-16 1650031200358  1650117600358  86400000
2022-04-17 1650117600358  1650204000358  86400000
2022-04-18 1650204000358  1650290400358  86400000
2022-04-19 1650290400359  1650376800359  86400000
2022-04-20 1650376800359  1650463200359  86400000
2022-04-21 1650463200359  1650549600359  86400000
2022-04-22 1650549600359  1650636000359  86400000
2022-04-23 1650636000360  1650722400360  86400000
2022-04-24 1650722400360  1650808800360  86400000
2022-04-25 1650808800360  1650895200360  86400000
2022-04-26 1650895200361  1650981600361  86400000
2022-04-27 1650981600361  1651068000361  86400000
2022-04-28 1651068000361  1651154400361  86400000
2022-04-29 1651154400362  1651240800362  86400000

More interestingly 2022-04-3 1am to 2 am return 7200004 milliseconds or 7200 seconds, while 12am to 1am return 3600 seconds.

public static void simpleTest(){
  Date d1 = new Date();
  d1.setMonth(3);
  d1.setDate(3);
  d1.setHours(0);
  d1.setMinutes(0);
  d1.setSeconds(0);

  Date d2 = new Date();
  d2.setMonth(3);
  d2.setDate(3);
  d2.setHours(1);
  d2.setMinutes(0);
  d2.setSeconds(0);
  long d1seconds = d1.getTime();
  long d2seconds = d2.getTime();
  long diff = (d2seconds - d1seconds);

  System.out.format(d1.toString() + "|"+ d2.toString() + "|Interval\n");
  System.out.format(" %d               %d                %d\n",d1seconds,d2seconds,diff);
}
Sun Apr 03 00:00:00 AEDT 2022|Sun Apr 03 01:00:00 AEDT 2022|Interval
 1648904400605               1648908000611                3600006
Sun Apr 03 01:00:00 AEDT 2022|Sun Apr 03 02:00:00 AEST 2022|Interval
     1648908000720               1648915200724                7200004<<<<<<<<<<<

https://docs.oracle.com/javase/7/docs/api/java/util/Date.html getTime(): Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.



Solution 1:[1]

Daylight savings time.

All those warnings you ignored? Don't ignore them. Date is a total lie.

It is not a date. It does not represent a date. It represents a moment in time. If you fail to heed these warnings and you attempt to treat it as a date, bugs and problems ensue.

There is no way to use Date to do date math. It just isn't suitable for it.

Use java.time and friends. You can pick your timezones, use sensible methods. There are no methods that don't make sense in anything in the java.time package.

Note that as a general point, 'how many nanoseconds are in a day' is not an answerable question. Days have variable lengths. Most days are 24 hours. Some are 23. Some are 25. Some don't exist (I guess that means they have 0 nanoseconds? I'm not talking about December 35th. I'm talking about real dates that were just skipped. For example when a country decides to move to the other side of the date line or when e.g. Russia decided to shift from the Julian to the Gregorian Calendar and therefore skipped half of a februari to match up dates).

You can talk about the general concept of a day, and say that it has exactly 24 hours. You can talk about the average if you want, too. But that is not quite exactly 24 hours, and then you must bring in '... where on the planet and in what era?'.

Perhaps take a step back. What ARE you trying to accomplish?

Examples of answerable questions:

  • How many nanos are in 24 hours. (Because 24 hours, unlike 'a day', is a precise definition).
  • How many nanos are there in April 21st, 2022, in zone Europe/Amsterdam.
  • How many nanos are there in an average day for all days in the year 2022 in zone America/New York.
  • How many nanos are there in a sidereal year.

Solution 2:[2]

Because April 3 is when New Zealand (and possibly other locations) ends Daylight Savings Time. Thus the clock adds one extra hour.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rzwitserloot
Solution 2 Elliott Frisch