Leap year problem
{{Short description|Issue resulting in miscalculation of leap years}}
{{Distinguish|Julian calendar#Leap year error}}
The leap year problem (also known as the leap year bug or the leap day bug) is a problem for both digital (computer-related) and non-digital documentation and data storage situations which results from errors in the calculation of which years are leap years, or from manipulating dates without regard to the difference between leap years and common years.
Categories
Leap year bugs typically fall into two categories, based on the amount of impact they may have in real-world usage:{{cite web |last1=Johnson-Pint |first1=Matt |title=What are some examples of leap year bugs? |url=https://stackoverflow.com/questions/57530882/what-are-some-examples-of-leap-year-bugs |website=Stack Overflow |accessdate=5 February 2020}}
- Those that lead to error conditions, such as exceptions, error return codes, uninitialized variables, or endless loops
- Those that lead to incorrect data, such as off-by-one problems in range queries or aggregation
Examples
=Python=
The following Python code is an example of a Category 1 leap year bug. It will work properly until today
becomes February 29. Then, it will attempt to create a February 29 of a common year, which does not exist. The date
constructor will raise a ValueError
with the message "day is out of range for month".{{cite web |last1=Johnson-Pint |first1=Matt |title=Python - Replacing the year |url=https://stackoverflow.com/a/60468711/634824 |website=Stack Overflow |accessdate=29 February 2020}}
from datetime import date
today = date.today()
later = today.replace(year = today.year + 1)
=Windows C++=
The following Windows C++ code is an example of a Category 1 leap year bug. It will work properly until the current date becomes February 29 of a leap year. Then, it will modify st
to represent February 29 of a common year, a date which does not actually exist. Passing st
to any function that accepts a SYSTEMTIME
struct as a parameter will likely fail.
For example, the SystemTimeToFileTime
call shown here will return an error code. Since that return value is unchecked (which is extremely common), this will result in ft
being left uninitialized.{{cite web |last1=Johnson-Pint |first1=Matt |title=Win32 / C++ SYSTEMTIME struct manipulation |url=https://stackoverflow.com/a/57530901/634824 |website=Stack Overflow |accessdate=5 February 2020}}
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
st.wYear++;
SystemTimeToFileTime(&st, &ft);
=Microsoft C#=
The following .NET C# code is an example of a Category 1 leap year bug. It will work properly until dt
becomes February 29. Then, it will attempt to create a February 29 of a common year, which does not exist. The DateTime
constructor will throw an ArgumentOutOfRangeException
.{{cite web |last1=Johnson-Pint |first1=Matt |title=.NET / C# - Construction from date parts |url=https://stackoverflow.com/a/57530883/634824 |website=Stack Overflow |accessdate=5 February 2020}}
DateTime dt = DateTime.Now;
DateTime result = new DateTime(dt.Year + 1, dt.Month, dt.Day);
=JavaScript=
The following JavaScript code is an example of a Category 2 leap year bug. It will work properly until dt
becomes February 29, such as on 2020-02-29. Then it will attempt to set the year to 2021. Since 2021-02-29 doesn't exist, the Date
object will roll forward to the next valid date, which is 2021-03-01.{{cite web |last1=Johnson-Pint |first1=Matt |title=JavaScript - Adding Year(s) |url=https://stackoverflow.com/a/59865749/634824 |website=Stack Overflow |accessdate=5 February 2020}}
var dt = new Date();
dt.setFullYear(dt.getFullYear() + 1);
=Bad leap year algorithm (many languages)=
The following code is an example of a leap year bug that is seen in many languages. It may cause either a Category 1 or Category 2 impact, depending on what the result is used for. It incorrectly assumes that a leap year occurs exactly every four years.{{cite web |last1=Johnson-Pint |first1=Matt |title=Determining if a Year is a Leap Year |url=https://stackoverflow.com/a/59865989/634824 |website=Stack Overflow |accessdate=5 February 2020}}
bool isLeapYear = year % 4 == 0;
The correct leap year algorithm is explained here: {{xref|{{slink|Leap year|Gregorian calendar}}}}.
Occurrences
{{See also|Year 2000 problem#On 29 February and 1 March 2000}}
- Microsoft Excel has, since its earliest versions, incorrectly considered 1900 to be a leap year, and therefore that February 29 comes between February 28 and March 1 of that year. The bug originated from Lotus 1-2-3, and was purposely implemented in Excel for the purpose of backward compatibility. Microsoft has written an article about this bug, explaining the reasons for treating 1900 as a leap year.[https://docs.microsoft.com/office/troubleshoot/excel/wrongly-assumes-1900-is-leap-year Excel incorrectly assumes that the year 1900 is a leap year]. Retrieved 2019-05-01. This bug has been promoted into a requirement in the Ecma Office Open XML (OOXML) specification.[http://www.ecma-international.org/publications/standards/Ecma-376.htm Standard ECMA-376 / Open Office XML File Formats]. Retrieved 2016-09-10.[http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html ISO/IEC 29500 / Open Office XML File Formats]. Retrieved 2016-09-10.
- In 1996, on December{{nbs}}31, at two aluminum smelting plants at Tiwai Point, New Zealand and Bell Bay, Tasmania, Australia, each of the 660 computers controlling the smelting potlines shut down at midnight since the computers were not programmed to handle the 366th day of the year (1996 being a leap year and having contained a February{{nbs}}29). Repair costs were estimated at more than {{NZD|1 million}}.{{cite journal |last1=Towler |first1=Jim |title=Leap-Year software bug gives "Million-dollar glitch" |url=https://catless.ncl.ac.uk/Risks/18.74.html#subj5 |journal=The RISKS Digest |date=7 January 1997 |volume=18 |issue=74 |publisher=ACM Committee on Computers and Public Policy |accessdate=5 February 2020}}
- In 2000, on December{{nbs}}31, in Norway the national railroad company Vy discovered all 29 of its new Signatur trains failed to run because their onboard computers did not recognize the date as the 366th day of the year. As an interim measure, engineers restarted the trains by resetting their clocks back by a month.{{cite web |url=http://news.bbc.co.uk/1/hi/sci/tech/1101917.stm |title=The last bite of the bug |website=BBC News |date=5 January 2001}}{{Cite news |title=7-Eleven Systems Hit by Y2k-like Glitch |url=https://www.computerworld.com/article/2590234/7-eleven-systems-hit-by-y2k-like-glitch.amp.html |access-date=10 March 2023}}{{Cite news |date=1 January 2001 |title=Y2K Bug Hits Norway's Railroad At End Of Year |language=en |url=https://greensboro.com/y2k-bug-hits-norways-railroad-at-end-of-year/article_82a866cf-3046-51ce-9aae-efd2bf3abc58.html |access-date=10 March 2023}}
- At midnight on December{{nbs}}31, 2008, many{{cite web|url=http://forums.zune.net/412486/ShowPost.aspx |title=Home - Microsoft Answers |publisher=Forums.zune.net |accessdate=2011-07-27 |url-status=dead |archiveurl=https://web.archive.org/web/20090830061109/http://forums.zune.net/412486/ShowPost.aspx |archivedate=August 30, 2009 }} first generation Zune 30 models froze.{{cite web |author=John Herrman |url=https://gizmodo.com/5121311/30gb-zunes-failing-everywhere-all-at-once |title=30GB Zunes Failing Everywhere, All At Once |publisher=Gizmodo.com |date=2008-12-31 |accessdate=2011-07-27 |archive-date=2011-08-12 |archive-url=https://web.archive.org/web/20110812004148/http://gizmodo.com/5121311/30gb-zunes-failing-everywhere-all-at-once |url-status=dead }}{{cite web|last=Geere |first=Duncan |url=http://www.techdigest.tv/2008/12/breaking_zunes.html |title=BREAKING: Zunes worldwide hit by mystery crash : Tech Digest |publisher=Techdigest.tv |date= 31 December 2008|accessdate=2011-07-27}} Microsoft stated that the problem was caused by the internal clock driver written by Freescale and the way the device handles a leap year. It automatically fixed itself 24 hours later, but an intermediate "fix" for those who did not wish to wait was to drain the device's battery and then recharge after noon UTC on January{{nbs}}1, 2009.{{cite web|url=http://www.zune.net/en-us/support/zune30.htm|title=Zune 30 FAQ|date=December 31, 2008|publisher=Microsoft|accessdate=January 1, 2009|archive-date=January 2, 2009|archive-url=https://web.archive.org/web/20090102065939/http://www.zune.net/en-us/support/zune30.htm|url-status=dead}}
{{cite web
|url=http://winjade.net/2009/01/lesson-on-infinite-loops/
|title=A lesson on infinite loops
|date=January 3, 2009
|publisher=AeroXperience
|first=Bryant
|last=Zadegan
|accessdate=January 5, 2009}}
- Sony's PlayStation 3 incorrectly treated 2010 as a leap year, so the non-existent February{{nbs}}29, 2010, was shown on March{{nbs}}1, 2010, and caused a program error {{xref|(see: {{slink|PlayStation 3|Leap year bug}})}}.{{cite news|url=https://metro.co.uk/2010/03/02/sony-fixes-ps3-leap-year-bug-138471/|title=Sony fixes PS3 leap year bug|newspaper=Metro|language=English|date=2 March 2010|accessdate=10 October 2019}}
- In 2012, TomTom satellite navigation devices malfunctioned due to a leap year bug that first emerged on March{{nbs}}31.{{cite news |title=TomTom sat-nav devices hit by GPS 'leap year bug' |work=BBC News |date=3 April 2012 |url=https://www.bbc.com/news/technology-17599701 |accessdate=5 February 2020}}
- In 2012, Gmail's chat history showed a date of December{{nbs}}31, 1969, for all chats saved on February 29.{{Citation needed|date=June 2015}}
- In 2012, Microsoft Azure was taken offline by a leap year bug on February{{nbs}}28 that caused virtual machines to crash upon startup. At 5:45 p.m. PST the Windows Azure team became aware of an issue, which was eventually discovered to be caused by a "one year from now" operation that involved changing the year without changing the day.{{cite web|url=http://azure.microsoft.com/en-us/blog/summary-of-windows-azure-service-disruption-on-feb-29th-2012/|title=Summary of Windows Azure Service Disruption on Feb 29th, 2012|date=9 March 2012|accessdate=23 January 2025|website=azure.microsoft.com}}
- In 2016, a large number of leap year bugs were cataloged in [https://codeofmatt.com/list-of-2016-leap-day-bugs List of 2016 Leap Day Bugs] at the website Code of Matt.{{cite web |last1=Johnson-Pint |first1=Matt |title=List of 2016 Leap Day Bugs |url=https://codeofmatt.com/list-of-2016-leap-day-bugs |website=Code of Matt |date=29 February 2016 |accessdate=5 February 2020}}
- In 2016, a leap year bug in the luggage conveyor system at Düsseldorf Airport on February{{nbs}}29 caused over 1,200 pieces of luggage to miss their flights.{{cite web |title=Airport hiccup leaves 100s of passengers pantless |url=https://www.thelocal.de/20160301/dsseldorf-airport-hick-ups-leave-hundreds-of-customers-without-underwear |website=The Local (de) |date=March 2016 |accessdate=5 February 2020}}
- In 2020, a large number of leap year bugs were cataloged in [https://codeofmatt.com/list-of-2020-leap-day-bugs List of 2020 Leap Day Bugs] at the website Code of Matt.{{cite web |last1=Johnson-Pint |first1=Matt |title=List of 2020 Leap Day Bugs |url=https://codeofmatt.com/list-of-2020-leap-day-bugs |website=Code of Matt |date=29 February 2020 |accessdate=9 March 2020}}
- In 2024, a large number of leap year bugs were cataloged in [https://codeofmatt.com/list-of-2024-leap-day-bugs/ List of 2024 Leap Day Bugs] at the website Code of Matt.{{Cite web |date=2024-02-29 |title=List of 2024 Leap Day Bugs |url=https://codeofmatt.com/list-of-2024-leap-day-bugs/ |access-date=2024-02-29 |website=Code of Matt |language=en}}
- In 2024, a leap year bug with the self-payment machines caused pay-at-pump fuelling stations in New Zealand to go offline for more than 10 hours.{{Cite web |date=2024-03-01 |title=Petrol pumps back online after day-long outage blamed on leap year glitch |url=https://www.nzherald.co.nz/hawkes-bay-today/news/february-29-allied-fuel-pumps-around-nz-ground-to-a-halt-as-systems-forget-leap-year/XEQBK5JLBZG6LO3VGUQ6Q2WGC4/ |access-date=2024-02-29 |website=The New Zealand Herald |language=en-NZ}}
See also
References
{{reflist}}
{{Year-related problems}}
{{DEFAULTSORT:Leap Year Bug}}