Ask HN: Did you encounter any leap year bugs today?
After a frantic scramble this morning, our billing team has finished patching a bug which erroneously was charging our monthly subscribers for an extra day.
All test suites are passing now, and SRE has scheduled a postmortem after the QA confirms the fix in 2028.
497 comments
[ 0.36 ms ] story [ 380 ms ] threadI guess this might be less-trivial if you've got a distributed multi-service architecture and perhaps also depend on APIs that aren't under your control in the first place.
It’s easy enough to address. There are various StackOverflow posts on such things. Here is one: https://stackoverflow.com/questions/54394327/using-datetime-...
Everything is use case dependent. Sometimes the use case is unimportant enough that mistakes are okay.
There's often someone out there who interprets such things as a 3 month, or 1 year retention policy and that it means they're entitled to look at the entire range whenever they want.
'subtract a year' is imprecise and has many meanings, if what you want is 'same day, same month, previous year' then say that and do that, that's conceptually `date.year -= 1` not `date -= 1 year`, and will have this bug.
Most jurisdictions use the 12 month standard, fwiw. I believe that's the ISO ruling as well, but I wasn't able to confirm that.
What is it? Does it attempt to return a datetime that's the same time as the input but 365 calendar days earlier (ignoring leap seconds? compensating for time zone changes?), or does it subtract 31536000 seconds from the current datetime? Because those aren't necessarily the same and it's ambiguous which one you mean by "subtract 365 days"
Yeah but this is bad code. Python certainly does have a "clean" way to subtract a year, you subtract a datetime.timedelta object.
Some other models (not F91W) does track year.
>Calendar system: Auto-calendar set at 28 days for February [0]
[0] https://support.casio.com/en/manual/009/qw593.pdf
https://en.wikipedia.org/wiki/ICA_AB
https://www.esmmagazine.com/retail/top-5-supermarket-retail-...
Is this why we can't have nice things?
https://www.reuters.com/world/asia-pacific/leap-year-glitch-...
Old programmer rant: In my day, we fixed the Y2K bug - we went to the future and back several times a day!
But then, come to think of it, you don't need to use SQL to have good date logic. C# and Java both have excellent date handing libraries. I don't know about C++, but I'd be surprised if there was not a modern date library for C++, so I am of the opinion there should be no excuses for software not to work on the 29th of Feb.
Use date handling functions and libraries that have been developed by people who know how to do it and have been battle tested.
The standard library now includes <chrono>. AFAIK: It was mostly written by Howard Hinnant. He now has more date/time libs that expand upon <chrono>: https://github.com/HowardHinnant/date
Self-pay gas station pumps break across NZ as software can't handle Leap Day - https://news.ycombinator.com/item?id=39553755 - Feb 2024 (31 comments)
Interestingly, Azure had this bug some years ago too leading to an outage. https://azure.microsoft.com/en-us/blog/summary-of-windows-az...
> During the morning on Thursday, no ICA store in Sweden could accept card payments. Instead, you had to use cash, Swish or pay via their app.
> The reason behind the problem was an internal problem in the payment systems at ICA as a result of an extra day in February, leap day.
ICA being the biggest grocery store chain in Sweden
At least it wasn't 3 days like when Coop's provider got hacked. They also handle our pay checks at work… makes me feel so safe :D
https://en.wikipedia.org/wiki/List_of_non-standard_dates#Feb...
https://it.wikipedia.org/wiki/Raffaele_Minichiello
AFAIK there is no firm convention. Feb is more natural ("My birthday is in February"), Mar is more logical (the 60th days of the year).
Anyway, I'm not sure there's any more or less logical date to use and Feb 29th babies seem to choose both about equally:
> “I love when people ask me, ‘Do you celebrate on Feb. 28 or March 1?’” said Raenell Dawn, a co-founder of Honor Society of Leap Year Day Babies. “I get to tell them, ‘Both, because I can.’ But I’m a February baby; I was not born in March.” An informal poll of the society’s members showed about a 50-50 split between the two dates, said Ms. Dawn, who is celebrating her “Sweeter 16” by turning 64 this year.
https://www.nytimes.com/2024/02/28/style/leap-year-explained...
If you want to celebrate your birthday at the moment earth reaches the same spot around the sun as when you were born, then we’d all have the same issue - we’d have to celebrate it 6 hours later every year, reseting every 4 years.
February 29 is very much a new day… which simply doesn’t exist on non-leap years.
If we're being scientific I guess all of us should move our birthday up by 1 day on leap years, but that seems annoying and not sure anyone really cares enough to.
Nasa explains:
365 +0.25 - 0.01 + 0.0025 - 0.00025 = 365.24225
https://pumas.nasa.gov/examples/how-many-days-are-year
Wait, is this right? omitting every 100 and adding every 400 should be enough.
EDIT: the 4000-year rule is just a proposal for now. So 365.2425 is correct.
https://youtu.be/FAdmpAZTH_M?si=r_INH_C5j9mbpJSh
"Feb 29 + 1 year" is verbatim restatement.
---
You can say Feb 29 + 365 days = Feb 28. (And Feb 29 + 730 days = Feb 27.)
---
EDIT:
Note that in the context of birthdays, people use "calendar years," not "unit of time which is ~1 revolution around the sun."
Birthdays aren't celebrated every X million seconds after the moment of birth.
They are celebrated the same day each calendar year -- notwithstanding the fuzzy concept of "same day" for incongruent calendar years. There's no singuar right answer, but that is the core question: "what is the same day next (calendar) year?"
[1] https://en.wikipedia.org/wiki/Begging_the_question
Correct.
> And Feb 29 + 730 days = Feb 27
Incorrect. It's Feb 28 again. In a normal, non-leap year, if you add 365 days then you get back to the same date.
As a surprise for a friend of mine, I threw him a gigasecond party on the day he turned 1000 million seconds old. Yes he was surprised, and a good time was had by all.
When I wrote "+ 1 year" I meant year to represent 365 or 365.25 days, not "the same day next year.":
You may have interpreted it as begging the question, but it was not my intent—though I admit my formulation was ambiguous.> Note that in the context of birthdays, people use "calendar years," not "unit of time which is ~1 revolution around the sun."
You've never heard someone say they've celebrated another trip around the Sun? I literally have a photo from 2007 of my daughter in Montessori celebrating her birthday by holding a globe and walking around a candle representing the Sun. I think most people probably don't really think about whether it's a calendar year or astronomical year because for most people, they are usually equivalent and it doesn't matter.
But that's all beside the point. All I meant to point out is that I disagree that March is more logical. I don't think logic points us to one month or the other. You may feel March is more logical, but I don't accept your priors, so for me March is not more logical than February.
Your calendar year birthday would be March 1 since one full calendar year has elapsed.
But Feb 28 is the nearest day to one full solar year, assuming you were born before about 6pm local time on Feb 29.
Two-day long birthday it is! :)
If you are born on 29th, on future 28th you are considered "too young", regardless whether a 29th exists or not. On future March 1st you are "old enough" again regardless.
If a 29th exists you are old enough already on that date. Drinking beer in Germany at 16, I guess in some countries at 20 could be relevant cases. For the more common minimum age of 18 for many things, the limit is reached always on March, 1st because a 29th cannot exist.
Tell us about your last marriage?, lol
https://codeofmatt.com/list-of-2024-leap-day-bugs/
[1] https://pandaily.com/hesai-technology-addresses-lidar-produc...
Telling base where, and when, you were
If you're measuring | controlling objects in the physical world (cars, rockets, etc) then you should not use unix time - those glitches will happen and instantaneous computations will go kooky.
https://en.wikipedia.org/wiki/Unix_time#Leap_seconds
You should use a monotonic clock with an arbitrary starting point anyway, unless you need some kind of synchronization between devices, but you probably wouldn't use unixtime there anyway.
So why bring it up then?
> You should use a monotonic clock with an arbitrary starting point anyway
Sure. We started doing that more than 50 years ago now when broad area geophysical surveying started off.
> unless you need some kind of synchronization between devices,
Can't see the problem - there are ways of syncing base station records against aircraft | boat | vehicle records in post processing .. all the stations, fixed or mobile, use a monotonic epoch based record structure that hold channel data and any sync marks that are broadcast by whatever means - raw GPS time serves well enough for a grain of 1.5 seconds, other marks can be used as required.
This is a fairly typical informal usage of the word correlation in my experience, and while it might not be _technically correct_ (I don't know, I'm not an expert), it's an often enough used idiom.
The bug simply was not "a good example of correlation does not equal causation" as any statistician would use the phrase. That's my only point. OP is free to type whatever words he wants into the comment box and press send
The confusing part, to me, is that Python would consider the above string to be parsed into a date in the first place, given that it has no year.
datetime.strptime('Feb 29 13:37:06.942', '%b %d %H:%M:%S.%f')
edit: added code example. import datetime from datetime first obvi
Edit: no it's not, it's absolutely correct, leap years just aren't as simple as I thought!
> However, there is still a small error that must be accounted for. To eliminate this error, the Gregorian calendar stipulates that a year that is evenly divisible by 100 (for example, 1900) is a leap year only if it is also evenly divisible by 400.
> For this reason, the following years are not leap years:
> 1700, 1800, 1900, 2100, 2200, 2300, 2500, 2600
I had no idea!
To be fair, it doesn't ask for year anywhere in settings. It simply doesn't know what year it is.
Not working on the game or anything but found it moderately amusing as someone who owns the game!
https://gamerant.com/theatrhythm-final-fantasy-bar-line-not-...