How could March 30th 2024 be followed by the 1st?

I am in the EU zone +1 or when DST is on, +2. Now is Sunday 31.3.2024. This Sunday morning, we changed into DST, at 2→3 (CETCEST).

I have Linux servers in separate networks reporting monthly energy consumption at 23:58 of the last day of the month. They have worked perfectly for many years. Networks are up to 8 hours travel apart!

Each server has an RTC and syncs NTP regularly. There are many safeguards if anything is suspicious, and three core servers in each network constantly check against each other whether everything, including the time, is OK. Yes, I am paranoid. I tolerate no (0) bugs. My systems work perfectly stable for many years. Worked, sorry.

Last night, at 23:58 of March 30th, all of my Raspberry Pi servers decided that the March 30th is followed by the 1st of the next month! I verified 7 (seven) different and independent ways per each network, that everything did really occur at March 30th within the minute 23:58! Confirmation includes 9 separate devices ignoring DST, plus an external US and an EU mail provider.

At 23:58 of each day, my servers do a bash test that can apparently go wrong many ways:

(( $(date -d tomorrow +"%-d") == 1 )) && ZadnjiDanMjeseca=1 || ZadnjiDanMjeseca=""

I do not see any way for this test to go wrong! I hope I am wrong. At this moment at 31.3.2024. Everything works perfectly fine, and zdump is correct! (The following example appears misformatted for me. There must be four distinct rows shown.)

hwclock; date; date -d tomorrow +"%-d"
2024-03-31 19:22:23.311664+02:00
ned, 31.03.2024.  19:22:23 CEST

The only way I can explain this issue is: The Linux distribution I use, Raspbian, somehow has two separate kernel functions calculating time. One of them, sadly, missed the fact that this is a leap year! Ups!

But, if so, why should it be limited to this Raspberry Pi OS version and kernel? Hell, Microsoft failed to make Excel calculate leap years correctly!

Over this weekend, I have seen several institutions (banks, our national tax office…) in my country having date related issues and closing the shop, too, so it seems not to be limited to Raspbian.

This goes against me as a programmer, but, I can find no alternative explanation. Hopefully, I am wrong…

Before posting, I made a switch from 23:58 to the 00:03 on the 1st, and where I must log data at 23:58 of the last day of the month, I test by adding 300 seconds, not asking for +1 day. These solutions should work.

So it is not buried in the comments: As I never use such calculations, I made a basic error in expecting "tomorrow" actually means tomorrow! It doesn’t make any sense to me; it means +1 day. So, I have expected these two commands produce the same output:

> date -d 'next tue'
uto,  2.04.2024.  00:00:00 CEST

> date -d 'tomorrow'
uto,  2.04.2024.  10:24:55 CEST

instead of having to type:

date -d "tomorrow 0"
Asked By: Pila


Well, I get:

# date -s '2024-03-30 23:58'; date -d tomorrow
Sat Mar 30 23:58:00 EET 2024
Mon Apr  1 00:58:00 EEST 2024

which isn’t really surprising since 24 hours after 2024-03-30 23:58 it is 2024-04-01 00:58. Just that the latter is in daylight savings time.

The manual says:

Relative items adjust a date (or the current date if none) forward or backward. The effects of relative items accumulate.
More precise units are […], ‘day’ worth 24 hours,
The string ‘tomorrow’ is worth one day in the future (equivalent to ‘day’),
When a relative item causes the resulting date to cross a boundary where the clocks were adjusted, typically for daylight saving time, the resulting date and time are adjusted accordingly.

The way to avoid issues like that is to ask for a time that’s not close to midnight.

E.g. noon-ish usually falls on the right day:

# date -s '2024-03-30 23:58'; date -d '+12 hours'
Sat Mar 30 23:58:00 EET 2024
Sun Mar 31 12:58:00 EEST 2024 

And this also seems to work:

# date -s '2024-03-30 23:58'; date -d '12:00 tomorrow'
Sat Mar 30 23:58:00 EET 2024
Sun Mar 31 12:00:00 EEST 2024
Answered By: ilkkachu
Categories: Answers Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.