Files
nexus/sreweekly/articles/414/09-happy-leap-day.html
2026-09-12 17:23:01 +08:00

574 lines
46 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Happy Leap Day! - The Pragmatic Engineer</title>
<meta name="HandheldFriendly" content="True" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" href="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w256h256/2024/06/The-Pragmatic-Engineer-Blog-Publication-Icon--Logo-.png">
<link rel="stylesheet" type="text/css" href="https://blog.pragmaticengineer.com/assets/css/screen.css?v=2YkU7oqFSRPn32Jc" />
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400" />
<meta name="description" content="29 February is causing problems in software systems across the globe. It’s a good reminder on how few assumptions we should make about dates – and why to use a date library when you can.">
<link rel="icon" href="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w256h256/2024/06/The-Pragmatic-Engineer-Blog-Publication-Icon--Logo-.png" type="image/png">
<link rel="canonical" href="https://blog.pragmaticengineer.com/happy-leap-day/">
<meta name="referrer" content="no-referrer-when-downgrade">
<meta property="og:site_name" content="The Pragmatic Engineer">
<meta property="og:type" content="article">
<meta property="og:title" content="Happy Leap Day!">
<meta property="og:description" content="29 February is causing problems in software systems across the globe. It’s a good reminder on how few assumptions we should make about dates – and why to use a date library when you can.">
<meta property="og:url" content="https://blog.pragmaticengineer.com/happy-leap-day/">
<meta property="og:image" content="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-11.15.23-1.png">
<meta property="article:published_time" content="2024-02-29T18:42:59.000Z">
<meta property="article:modified_time" content="2024-02-29T20:15:29.000Z">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Happy Leap Day!">
<meta name="twitter:description" content="29 February is causing problems in software systems across the globe. It’s a good reminder on how few assumptions we should make about dates – and why to use a date library when you can.">
<meta name="twitter:url" content="https://blog.pragmaticengineer.com/happy-leap-day/">
<meta name="twitter:image" content="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-11.15.23-1.png">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Gergely Orosz">
<meta name="twitter:site" content="@GergelyOrosz">
<meta name="twitter:creator" content="@GergelyOrosz">
<meta property="og:image:width" content="1082">
<meta property="og:image:height" content="1210">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"publisher": {
"@type": "Organization",
"name": "The Pragmatic Engineer",
"url": "https://blog.pragmaticengineer.com/",
"logo": {
"@type": "ImageObject",
"url": "https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2015/12/pragmatic-engineer-profile-image.png"
}
},
"author": {
"@type": "Person",
"name": "Gergely Orosz",
"url": "https://blog.pragmaticengineer.com/author/gergely/",
"sameAs": [
"https://x.com/GergelyOrosz"
]
},
"headline": "Happy Leap Day!",
"url": "https://blog.pragmaticengineer.com/happy-leap-day/",
"datePublished": "2024-02-29T18:42:59.000Z",
"dateModified": "2024-02-29T20:15:29.000Z",
"image": {
"@type": "ImageObject",
"url": "https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-11.15.23-1.png",
"width": 1082,
"height": 1210
},
"description": "29 February is causing problems in software systems across the globe. It’s a good reminder on how few assumptions we should make about dates – and why to use a date library when you can.",
"mainEntityOfPage": "https://blog.pragmaticengineer.com/happy-leap-day/"
}
</script>
<meta name="generator" content="Ghost 6.64">
<link rel="alternate" type="application/rss+xml" title="The Pragmatic Engineer" href="https://blog.pragmaticengineer.com/rss/">
<script defer src="https://cdn.jsdelivr.net/ghost/portal@~2.71/umd/portal.min.js" data-i18n="true" data-ghost="https://blog.pragmaticengineer.com/" data-key="e19be39046770b14a9d5caceb0" data-api="https://pragmatic-engineer.ghost.io/ghost/api/content/" data-locale="en" crossorigin="anonymous"></script><style id="gh-members-styles">.gh-post-upgrade-cta-content,
.gh-post-upgrade-cta {
display: flex;
flex-direction: column;
align-items: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
text-align: center;
width: 100%;
color: #ffffff;
font-size: 16px;
}
.gh-post-upgrade-cta-content {
border-radius: 8px;
padding: 40px 4vw;
}
.gh-post-upgrade-cta h2 {
color: #ffffff;
font-size: 28px;
letter-spacing: -0.2px;
margin: 0;
padding: 0;
}
.gh-post-upgrade-cta p {
margin: 20px 0 0;
padding: 0;
}
.gh-post-upgrade-cta small {
font-size: 16px;
letter-spacing: -0.2px;
}
.gh-post-upgrade-cta a {
color: #ffffff;
cursor: pointer;
font-weight: 500;
box-shadow: none;
text-decoration: underline;
}
.gh-post-upgrade-cta a:hover {
color: #ffffff;
opacity: 0.8;
box-shadow: none;
text-decoration: underline;
}
.gh-post-upgrade-cta a.gh-btn {
display: block;
background: #ffffff;
text-decoration: none;
margin: 28px 0 0;
padding: 8px 18px;
border-radius: 4px;
font-size: 16px;
font-weight: 600;
}
.gh-post-upgrade-cta a.gh-btn:hover {
opacity: 0.92;
}</style>
<script defer src="https://cdn.jsdelivr.net/ghost/sodo-search@~1.8/umd/sodo-search.min.js" data-key="e19be39046770b14a9d5caceb0" data-styles="https://cdn.jsdelivr.net/ghost/sodo-search@~1.8/umd/main.css" data-sodo-search="https://pragmatic-engineer.ghost.io/" data-locale="en" crossorigin="anonymous"></script>
<link href="https://blog.pragmaticengineer.com/webmentions/receive/" rel="webmention">
<script defer src="/public/cards.min.js?v=ShRHxgy4po8zN-Wf"></script>
<link rel="stylesheet" type="text/css" href="/public/cards.min.css?v=WwnU9jw5ancNC8Gc">
<script defer src="/public/member-attribution.min.js?v=AKG4hWena9j3yX3I"></script>
<script defer src="/public/ghost-stats.min.js?v=vFcCUf6ZQ0Hyhc8h" data-stringify-payload="false" data-datasource="analytics_events" data-storage="localStorage" data-host="https://blog.pragmaticengineer.com/.ghost/analytics/api/v1/page_hit" tb_site_uuid="39f85cc7-8637-40fc-a57c-f45754453717" tb_post_uuid="34ffd1de-eb59-44c1-9a37-6747c1425a38" tb_post_type="post" tb_member_uuid="undefined" tb_member_status="undefined" tb_gift_link=""></script><style>:root {--ghost-accent-color: #15171A;}</style>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/line-numbers/prism-line-numbers.min.css" />
<style>
pre[class*=language-] {
margin: 1.75em 0;
}
</style>
</head>
<body class="post-template nav-closed">
<div class="nav mobile">
<h3 class="nav-title">Menu</h3>
<a href="#" class="nav-close">
<span class="hidden">Close</span>
</a>
<ul>
<li class="nav-home elusive-icon Home" role="presentation"><a href="https://blog.pragmaticengineer.com/">Home</a></li>
<li class="nav-newsletter elusive-icon Newsletter" role="presentation"><a href="https://newsletter.pragmaticengineer.com/about">Newsletter</a></li>
<li class="nav-podcast elusive-icon Podcast" role="presentation"><a href="https://pragmaticpodcast.com">Podcast</a></li>
<li class="nav-sponsors elusive-icon Sponsors" role="presentation"><a href="https://blog.pragmaticengineer.com/sponsors/">Sponsors</a></li>
<li class="nav-ethics-statement elusive-icon Ethics statement" role="presentation"><a href="https://blog.pragmaticengineer.com/ethics-statement/">Ethics statement</a></li>
<li class="nav-now elusive-icon Now" role="presentation"><a href="https://blog.pragmaticengineer.com/now/">Now</a></li>
<li class="nav-my-books elusive-icon My Books" role="presentation"><a href="https://blog.pragmaticengineer.com/books/">My Books</a></li>
<li class="nav-early-trends elusive-icon Early trends" role="presentation"><a href="https://blog.pragmaticengineer.com/early-trends/">Early trends</a></li>
<li class="nav-investing elusive-icon Investing" role="presentation"><a href="https://blog.pragmaticengineer.com/investing/">Investing</a></li>
<li class="nav-contact-me elusive-icon Contact me" role="presentation"><a href="https://blog.pragmaticengineer.com/contact/">Contact me</a></li>
<li class="nav-about elusive-icon About" role="presentation"><a href="https://blog.pragmaticengineer.com/about/">About</a></li>
<li class="nav-rss-feed elusive-icon RSS Feed" role="presentation"><a href="https://blog.pragmaticengineer.com/feed/">RSS Feed</a></li>
<li class="nav-bluesky elusive-icon bluesky" role="presentation"><a href="https://bsky.app/profile/gergely.pragmaticengineer.com/">bluesky</a></li>
<li class="nav-twitter elusive-icon twitter" role="presentation"><a href="http://twitter.com/GergelyOrosz">twitter</a></li>
<li class="nav-youtube elusive-icon youtube" role="presentation"><a href="https://www.youtube.com/@pragmaticengineer">youtube</a></li>
<li class="nav-linkedin elusive-icon linkedin" role="presentation"><a href="http://www.linkedin.com/in/gergelyorosz">linkedin</a></li>
</ul>
<a class="subscribe-button icon-feed" href="https://blog.pragmaticengineer.com/rss/">Subscribe</a>
</div>
<span class="nav-cover mobile"></span>
<div class="nav-desktop">
<ul class="sidebar-nav">
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/" class="elusive-icon Home" rel="me">Home</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://newsletter.pragmaticengineer.com/about" class="elusive-icon Newsletter" rel="me">Newsletter</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://pragmaticpodcast.com" class="elusive-icon Podcast" rel="me">Podcast</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/sponsors/" class="elusive-icon Sponsors" rel="me">Sponsors</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/ethics-statement/" class="elusive-icon Ethics statement" rel="me">Ethics statement</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/now/" class="elusive-icon Now" rel="me">Now</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/books/" class="elusive-icon My Books" rel="me">My Books</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/early-trends/" class="elusive-icon Early trends" rel="me">Early trends</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/investing/" class="elusive-icon Investing" rel="me">Investing</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/contact/" class="elusive-icon Contact me" rel="me">Contact me</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/about/" class="elusive-icon About" rel="me">About</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/feed/" class="elusive-icon RSS Feed" rel="me">RSS Feed</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://bsky.app/profile/gergely.pragmaticengineer.com/" class="elusive-icon bluesky" rel="me">bluesky</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="http://twitter.com/GergelyOrosz" class="elusive-icon twitter" rel="me">twitter</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://www.youtube.com/@pragmaticengineer" class="elusive-icon youtube" rel="me">youtube</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="http://www.linkedin.com/in/gergelyorosz" class="elusive-icon linkedin" rel="me">linkedin</a>
</li>
</ul>
</div>
<div class="site-wrapper">
<header class="main-header post-head " style="background-image: url(https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-11.15.23-1.png)">
<nav class="main-nav overlay clearfix">
<a class="blog-logo" href="https://blog.pragmaticengineer.com"><img src="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2015/12/pragmatic-engineer-profile-image.png" alt="The Pragmatic Engineer" /></a>
<a class="menu-button icon-menu" href="#"><span class="word">Menu</span></a>
</nav>
</header>
<main class="content" role="main">
<article class="post">
<header class="post-header">
<h1 class="post-title">Happy Leap Day!</h1>
</header>
<section class="post-content" id="content">
<!--
<p><em>Before we start: I'm hosting the first-ever <strong><a href="https://www.pragmaticsummit.com/">The Pragmatic Summit</a></strong> on 11 February, 2026, in San Francisco. Join 400 top engineers and leaders as we answer the question: How is AI reshaping software engineering, dev workflows, and the modern engineering stack?
Spaces are limited - don't miss out! <strong><a href="https://www.pragmaticsummit.com/">Buy tickets here</a></strong>.
</em></p>
-->
<p><em>👋 Hi, this is</em><a href="https://twitter.com/gergelyorosz?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow"><em> Gergely</em></a><em> with a bonus, free issue of the Pragmatic Engineer Newsletter. In every issue, I cover topics related to Big Tech and startups through the lens of engineering managers and senior engineers. In this article, we cover one out of three topics from today’s subscriber-only </em><a href="https://newsletter.pragmaticengineer.com/p/the-pulse-83?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow"><em>The Pulse issue</em></a><em>. </em><a href="https://newsletter.pragmaticengineer.com/about?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow"><em>Subscribe</em></a><em> to get issues like this in your inbox, every week.</em></p><p>It’s 29th February, a once-every-four-year occurrence. Most people don’t think too much about this extra day in the calendar, but as software engineers, we absolutely should! But first, a few current cases of systems whose developers didn’t:</p><p><strong>In Sweden, card payments are down at a leading supermarket chain. </strong>ICA is the biggest supermarket chain in the Nordic country, and today customers can only use cash. From Swedish online magazine <a href="https://omni.se/gar-inte-betala-med-kort-pa-ica-skottdagsproblem/a/dwxO8B?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">Omni.se</a>:</p><blockquote>“The problem [with card payments] is due to today's date. The information I received is that today is the shooting day. It is therefore a leap day problem and it is February 29 that simply causes it, says store manager Peter Slagbrand to Eskilstuna-Kuriren.<br><br>The information about the leap day problem is confirmed by the ICA bank's press officer Maria Elfvelin.”</blockquote><p><strong>In Colombia, airline tickets have been printed incorrectly by the nation’s largest airline. </strong>Airline Avianca printed tickets dated as 3/1 instead of 2/29, thanks to their system not accounting for the leap day. A traveler shared how the airline recognized the mistake, fixed it on the day, and <a href="https://x.com/ShellWinger/status/1763118783302881395?s=20&ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">sent this email</a> to customers:</p><blockquote>“We inform you that if your flight is on February 29, 2024, you may experience a discrepancy in the date of your flight on the boarding pass. To ensure you have the correct information, please download it again from avianca.com or from our app.”</blockquote><p><strong>Payment terminals at gas stations stopped working in New Zealand. </strong>The New Zealand Herald <a href="https://www.nzherald.co.nz/nz/february-29-allied-fuel-pumps-around-nz-ground-to-a-halt-as-systems-forget-leap-year/XEQBK5JLBZG6LO3VGUQ6Q2WGC4/?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">reports</a>:</p><blockquote>“Petrol stations around the country are up and running again following a day-long leap-year glitch which saw card payment machines go down for more than 10 hours.<br><br>Allied Petroleum, Gull, Z, Waitomo and other fuel stops around New Zealand reported problems with card payments on Thursday because of a software glitch they said was caused by their systems not being programmed to deal with the date February 29.”</blockquote><p><strong>A smartwatch released this year couldn’t display today’s date. </strong>The Fastrack FS1 is a recently released smartwatch from the Indian company, Fastrack. The FS1 model was released in March 2023, and here’s what it says is the date today:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-11.15.23.png" class="kg-image" alt="" loading="lazy" width="1082" height="1210" srcset="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w600/2024/02/Screenshot-2024-02-29-at-11.15.23.png 600w, https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w1000/2024/02/Screenshot-2024-02-29-at-11.15.23.png 1000w, https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-11.15.23.png 1082w" sizes="(min-width: 720px) 720px"><figcaption><i><em class="italic" style="white-space: pre-wrap;">The first time this watch saw a leap day – and it wasn’t prepared. Source: </em></i><a href="https://x.com/Manuvktr/status/1763057415417901311?s=20&ref=blog.pragmaticengineer.com" target="_blank" rel="noopener noreferrer nofollow"><i><em class="italic" style="white-space: pre-wrap;">Manu Varghese on X</em></i></a></figcaption></figure><p><strong>An EA Sports racing game is unplayable today. </strong>EA SPORTS WRC (World Rally Championship) is a rally racing game, released in November 2023 for Windows, Xbox and Playstation. Those trying to play the game today cannot: because it crashes. The workaround EA Sports <a href="https://x.com/EAHelp/status/1763192739322085598?s=20&ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">suggests</a> is to set your system date to 1st of March – or perhaps just take a break from playing today!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-19.28.47.png" class="kg-image" alt="" loading="lazy" width="1792" height="1006" srcset="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w600/2024/02/Screenshot-2024-02-29-at-19.28.47.png 600w, https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w1000/2024/02/Screenshot-2024-02-29-at-19.28.47.png 1000w, https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/size/w1600/2024/02/Screenshot-2024-02-29-at-19.28.47.png 1600w, https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/02/Screenshot-2024-02-29-at-19.28.47.png 1792w" sizes="(min-width: 720px) 720px"><figcaption><i><em class="italic" style="white-space: pre-wrap;">EA Sports WRC is a recent game that also cannot handle today’s leap day. Image source: </em></i><a href="https://www.pushsquare.com/features/preview-ea-sports-wrc-combines-codemasters-pedigree-with-authentic-rally-racing?ref=blog.pragmaticengineer.com" target="_blank" rel="noopener noreferrer nofollow"><i><em class="italic" style="white-space: pre-wrap;">Pushsquare</em></i></a></figcaption></figure><p>This crash is notable, given the games industry invests more heavily than most other companies into quality assurance and thorough testing of the games. It is further proof on how easy it is to forget about an edge case that comes up just five months after the release of the game.</p><p><strong>Driving license issuance disrupted in Japan. </strong>Japan Today <a href="https://japantoday.com/category/national/leap-year-glitch-disrupts-driver-license-issuance-by-japan-police?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">writes</a>:</p><blockquote>“Police departments in some Japanese prefectures were unable to issue driver's licenses Thursday, apparently due to a system glitch linked to the leap year. The extra day at the end of February appears to have triggered a system error related to time and date functions.<br><br>Police departments in Niigata, Kanagawa, Okayama and Ehime prefectures faced problems from the morning, such as being unable to send personal data from the driver management system to the machines that issue licenses. The system was almost fully restored before noon.”</blockquote><p>I will give a hat tip to the <em>“almost fully restored before noon” </em>mention. You can imagine the engineer who was asked by a business stakeholder: “is it fixed yet?” and who answers: “Almost – I’ve now resolved 90% of the issues.” Which we all know means there’s still the second 90% left to resolve – because resolving those last edge cases often take just as much time as fixing the first 90% did! <em>I’m being sarcastic, but this is often how it goes with bugs not encountered before.</em></p><p>There are several more cases of systems failing today, as collected by software engineer Matt Johnson-Pint in his post, <a href="https://codeofmatt.com/list-of-2024-leap-day-bugs/?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">List of 2024 Leap Day Bugs</a>.</p><p><strong>Expect more bugs this 31 December. </strong>After 29 February, we’re not done with leap day-related glitches. New Year’s Eve holds another nasty surprise for systems that assume a year is 365 days long. This year has 366 days.</p><p>Some consequences can be very serious. In 1996, an aluminum smelting plant in New Zealand was damaged when the factory abruptly shut down in the first few seconds of 31 December! As the New Zealand Press Association <a href="https://web.archive.org/web/19990116222711/https://catless.ncl.ac.uk/Risks/18.74.html#subj5" rel="noopener noreferrer nofollow">wrote in 1997</a>:</p><blockquote>“A computer glitch at the Tiwai Pt [place in South Island of New Zealand] aluminum smelter at midnight on New Year's Eve has left a repair bill of more than $1 million [New Zealand Dollars]. Production in all the smelting potlines ground to a halt at the stroke of midnight when the computers shut down simultaneously and without warning.&nbsp;<br><br>New Zealand Aluminium Smelters' general manager David Brewer said the failure was traced to a faulty computer software programme, which failed to account for 1996 being a leap year. The computer was not programmed to handle the 366th day of the year, he said. "Each of the 660 process control computers hung up simultaneously at midnight," Mr Brewer said.”<br><br>The same problem occurred two hours later at Comalco's Bell Bay smelter, in Tasmania [Australia]. New Zealand is two hours ahead of Tasmania. Both smelters use the same programme, which was written by Comalco computer staff. (...)<br><br>Tiwai staff rallied through the night to operate the potlines manually and try to find the cause. The glitch was fixed and normal production restored by midafternoon. However, by then, the damage had been done. Without the computers to regulate temperatures inside the pot cells, five cells overheated and were damaged beyond repair. Mr Brewer said they would have to be replaced at a cost of more than $1 million.”</blockquote><p>In 2008, Zune (Microsoft’s 30GB music player) <a href="https://www.computerworld.com/article/2529992/zune-chokes-on-leap-year-bug.html?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">stopped working</a> on 31 December because of a leap year bug, which sent devices into an infinite loop. At the time, Microsoft had invested the most into a testing culture, with one dedicated SDET (software development engineer in test) for every 2 SDEs (software engineers.)&nbsp;</p><p>Yet this bug slipped through the cracks! <em>We cover more on Microsoft’s QA approach and the later retirement of the SDET role in </em><a href="https://newsletter.pragmaticengineer.com/p/how-big-tech-does-qa?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow"><em>How Big Tech does Quality Assurance</em></a><em>.</em></p><p><strong>So, how do you account for Leap Days when building systems? </strong>A couple of things will help:</p><ul><li>Use Date objects and operations on them: e.g. increment the date object by a year, instead of adding 365 days to it. Framework-level date classes tend to account for leap years – it’s a big reason to use them!</li><li>Do not assume February always has 28 days</li><li>For that reason, don’t assume every year has 365 days</li></ul><p>This list is not exhaustive. What is exhaustive is a list on GitHub: <a href="https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">Falsehoods programmers believe about time</a>. It’s a very long list, with 112 falsehoods named. Here are 10 of my favorites:</p><blockquote>“Don't reinvent a date time library yourself. If you think you understand everything about time, you're probably doing it wrong.<br><br><strong>Falsehoods</strong> <br>- There are always 24 hours in a day.<br> <br>- February is always 28 days long.<br> <br>- Months have either 28, 29, 30, or 31 days.<br> <br>- The day before Saturday is always Friday.<br> <br>- GMT and UTC are the same timezone.<br><br>- Any 24-hour period will always begin and end in the same day (or week, or month).&nbsp;<br><br>- The difference between two timestamps is an accurate measure of the time that elapsed between them.<br><br>- Daylight saving time always adjusts by an hour.<br><br>- Time always goes forwards.”</blockquote><p>The last note is particularly notable on how time <em>can</em> move backwards – at least in terms of what the time is. While the absolute seconds will always will always increment: when daylight savings end, clocks are winded back an hour: one minute after 1:59am on Saturday, it is not 2am but 1am!</p><p>There are some things, however, that are safe to assume, because they are always true. For example, a month always has <em>at least</em> 28 days. So, if you are to hardcode a monthly recurring charge to repeat on a specific day of the month: doing this on or before the 28th <em>should</em> be safe enough.</p><p>I now invite you to <a href="https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">read the full list</a>, then inspect code you’ve previously written containing assumptions about dates and time. Can you replace it with a date library that accounts for (hopefully) <em>all</em> of the above?</p><hr><p>This was one out of the three topics covered in this week’s The Pulse. The full edition additionally covers:</p><ul><li><strong>Klarna’s AI chatbot: how revolutionary is it, really?</strong> Klarna launched its AI chatbot, built in collaboration with OpenAI, which the company wants to use to eliminate 2/3rds of customer support positions. But is it as revolutionary, and as likely to replace jobs, as Klarna claims? My take is that it’s a well-written bot, but I’m dubious that it’s as disruptive as that.</li><li><strong>Affirm paid $10M for Fast’s engineering team. </strong>As the one-click startup ran out of money, its then head of engineering brokered a deal with buy-now-pay-later scaleup Affirm, which paid $10M in cash in return to give out offers to 80-90 Fast software engineers.</li></ul><p><a href="https://newsletter.pragmaticengineer.com/p/the-pulse-83?ref=blog.pragmaticengineer.com" rel="noopener noreferrer nofollow">Read the full The Pulse here.</a></p>
<!-- Newsletter -->
<p>
<a href="https://newsletter.pragmaticengineer.com/about">Subscribe to my weekly newsletter</a> to get articles like this in your inbox. It's a pretty good read - and the <a href="https://substack.com/top/technology">#1 software engineering newsletter</a> on Substack.
</p>
</section>
<footer class="post-footer">
<section class="podcast-details">
<h4>The Pragmatic Engineer Podcast</h4>
<p>
Deepdives with experienced engineers and tech professionals who share their hard-earned lessons, interesting stories and advice they have on building software.
</p>
<p>
Listen to it <a href="https://open.spotify.com/show/2Bho9xCbOQMWMJ7UKmqCzD">on Spotify</a>, on <a href="https://podcasts.apple.com/us/podcast/the-pragmatic-engineer/id1769051199">Apple</a>, on <a href="https://www.youtube.com/@pragmaticengineer">YouTube</a>, or <a href="https://pragmaticpodcast.com/">on the web</a>.
</p>
</section>
<section class="book-details">
<h4>The Software Engineer's Guidebook</h4>
<p>
I wrote <a href="https://www.engguidebook.com/">The Software Engineer's Guidebook</a>. Here is what Tanya Reilly, senior principal engineer and author of <a href="https://www.oreilly.com/library/view/the-staff-engineers/9781098118723/">The Staff Engineer's Path</a> says about it:
</p>
<blockquote>
"From performance reviews to P95 latency, from team dynamics to testing, Gergely demystifies all aspects of a software career. This book is well named: <strong>it really does feel like the missing guidebook for the whole industry.</strong>"
</blockquote>
<p style="padding-top:20px">
<a href="https://www.engguidebook.com/">
<img src="/assets/img/EngGuidebook.jpg" alt="The Software Engineer's Guidebook" style="width: 100%; max-width: 300px; margin: 0 auto; display: block;"/>
</a>
</p>
<p>
<a href="https://www.engguidebook.com/">Get the book here.</a>
</p>
</section>
<section class="conference-details">
<h4>Annual conference talk</h4>
<p>
Every year, I do one conference talk in the US, and one in Europe. <strong>My next conference talk is at <a href="https://leaddev.com/leaddev-new-york/?utm_source=pragmaticengineer&utm_medium=email&utm_campaign=pragmaticengineer">LDX3 New York</a>, on 15 September 2026.</strong>
Previous talks:
</p>
<ul>
<li><a href="https://newsletter.pragmaticengineer.com/p/slow-down-to-speed-up">Slow down to speed up</a> - Craft Conference, 2026</li>
<li><a href="https://newsletter.pragmaticengineer.com/p/software-engineering-with-llms-in-2025">Software engineering with LLMs: reality check</a> - LDX3, London, 2025</li>
</ul>
<p>
<strong>
</strong>
</p>
<!--
In 2025, this will be at <a href="https://leaddev.com/leaddev-london/?utm_source=the-pragmatic-engineer&utm_medium=newsletter-social&utm_campaign=LON25-media-community-partner">LDX3 (formerly: LeadDev)</a> in London, 16 June 2025. My keynote is titled "Software engineering with GenAI." If you'll <a href="https://leaddev.com/leaddev-london/?utm_source=the-pragmatic-engineer&utm_medium=newsletter-social&utm_campaign=LON25-media-community-partner">be there</a>, come say hi!
-->
</section>
<section class="newsletter" id="newsletter-second"> <!-- Section that gets moved up -->
<h4>Newsletter</h4>
<p>
Enjoying this article? <a href="https://newsletter.pragmaticengineer.com/about">Subscribe to my newsletter</a> to get issues like this in your inbox. It's a good read and the <a href="https://substack.com/top/technology">#1 software engineering / AI engineering newsletter</a> on Substack.
</p>
</section>
<section class="authorAndShare">
<section class="author">
<h4><a href="/author/gergely/">Gergely Orosz</a></h4>
<section class="post-meta">
Last updated <time class="post-date" datetime="2024-02-29">29 February 2024</time>. Originally published 29 Feb 2024.
<br>&copy; Gergely Orosz, 2024
</section>
<p>Writing The Pragmatic Engineer Newsletter. Author of The Software Engineer&#x27;s Guidebook. Previously at Uber, Microsoft, Skype, Skyscanner.</p>
<div class="author-meta">
<span class="author-location icon-location">Amsterdam, Netherlands</span>
</div>
</section>
<section class="share">
<h4>Share this post</h4>
<a class="icon-twitter" href="https://twitter.com/intent/tweet?text=Happy%20Leap%20Day!&amp;url=https://blog.pragmaticengineer.com/happy-leap-day/"
onclick="window.open(this.href, 'twitter-share', 'width=550,height=235');return false;">
<span class="hidden">Twitter</span>
</a>
<a class="icon-facebook" href="https://www.facebook.com/sharer/sharer.php?u=https://blog.pragmaticengineer.com/happy-leap-day/"
onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;">
<span class="hidden">Facebook</span>
</a>
</section>
<section>
</footer>
</article>
</main>
<aside class="sidebar">
<img class="profile-image" src="https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2015/12/pragmatic-engineer-profile-image.png" alt="" />
<!--
// to display a custom image, copy the image into assets/img/profile-img.png and replace the previous line with this:
<img class="profile-image" src="https://blog.pragmaticengineer.com/assets/img/profile-image.png?v=0ccd6679d9" alt="" />
-->
<section class="publisher">by <strong>Gergely Orosz</strong></section>
<div class="nav mobile">
<h3 class="nav-title">Menu</h3>
<a href="#" class="nav-close">
<span class="hidden">Close</span>
</a>
<ul>
<li class="nav-home elusive-icon Home" role="presentation"><a href="https://blog.pragmaticengineer.com/">Home</a></li>
<li class="nav-newsletter elusive-icon Newsletter" role="presentation"><a href="https://newsletter.pragmaticengineer.com/about">Newsletter</a></li>
<li class="nav-podcast elusive-icon Podcast" role="presentation"><a href="https://pragmaticpodcast.com">Podcast</a></li>
<li class="nav-sponsors elusive-icon Sponsors" role="presentation"><a href="https://blog.pragmaticengineer.com/sponsors/">Sponsors</a></li>
<li class="nav-ethics-statement elusive-icon Ethics statement" role="presentation"><a href="https://blog.pragmaticengineer.com/ethics-statement/">Ethics statement</a></li>
<li class="nav-now elusive-icon Now" role="presentation"><a href="https://blog.pragmaticengineer.com/now/">Now</a></li>
<li class="nav-my-books elusive-icon My Books" role="presentation"><a href="https://blog.pragmaticengineer.com/books/">My Books</a></li>
<li class="nav-early-trends elusive-icon Early trends" role="presentation"><a href="https://blog.pragmaticengineer.com/early-trends/">Early trends</a></li>
<li class="nav-investing elusive-icon Investing" role="presentation"><a href="https://blog.pragmaticengineer.com/investing/">Investing</a></li>
<li class="nav-contact-me elusive-icon Contact me" role="presentation"><a href="https://blog.pragmaticengineer.com/contact/">Contact me</a></li>
<li class="nav-about elusive-icon About" role="presentation"><a href="https://blog.pragmaticengineer.com/about/">About</a></li>
<li class="nav-rss-feed elusive-icon RSS Feed" role="presentation"><a href="https://blog.pragmaticengineer.com/feed/">RSS Feed</a></li>
<li class="nav-bluesky elusive-icon bluesky" role="presentation"><a href="https://bsky.app/profile/gergely.pragmaticengineer.com/">bluesky</a></li>
<li class="nav-twitter elusive-icon twitter" role="presentation"><a href="http://twitter.com/GergelyOrosz">twitter</a></li>
<li class="nav-youtube elusive-icon youtube" role="presentation"><a href="https://www.youtube.com/@pragmaticengineer">youtube</a></li>
<li class="nav-linkedin elusive-icon linkedin" role="presentation"><a href="http://www.linkedin.com/in/gergelyorosz">linkedin</a></li>
</ul>
<a class="subscribe-button icon-feed" href="https://blog.pragmaticengineer.com/rss/">Subscribe</a>
</div>
<span class="nav-cover mobile"></span>
<div class="nav-desktop">
<ul class="sidebar-nav">
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/" class="elusive-icon Home" rel="me">Home</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://newsletter.pragmaticengineer.com/about" class="elusive-icon Newsletter" rel="me">Newsletter</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://pragmaticpodcast.com" class="elusive-icon Podcast" rel="me">Podcast</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/sponsors/" class="elusive-icon Sponsors" rel="me">Sponsors</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/ethics-statement/" class="elusive-icon Ethics statement" rel="me">Ethics statement</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/now/" class="elusive-icon Now" rel="me">Now</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/books/" class="elusive-icon My Books" rel="me">My Books</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/early-trends/" class="elusive-icon Early trends" rel="me">Early trends</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/investing/" class="elusive-icon Investing" rel="me">Investing</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/contact/" class="elusive-icon Contact me" rel="me">Contact me</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/about/" class="elusive-icon About" rel="me">About</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://blog.pragmaticengineer.com/feed/" class="elusive-icon RSS Feed" rel="me">RSS Feed</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://bsky.app/profile/gergely.pragmaticengineer.com/" class="elusive-icon bluesky" rel="me">bluesky</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="http://twitter.com/GergelyOrosz" class="elusive-icon twitter" rel="me">twitter</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="https://www.youtube.com/@pragmaticengineer" class="elusive-icon youtube" rel="me">youtube</a>
</li>
<li class="nav-desktop" role="presentation">
<a href="http://www.linkedin.com/in/gergelyorosz" class="elusive-icon linkedin" rel="me">linkedin</a>
</li>
</ul>
</div>
<ul>
<li><a href="https://blog.pragmaticengineer.com/newsletter" class="elusive-icon email">Subscribe via email</a></li>
<li><a href="http://feeds.feedburner.com/ThePragmaticEngineer" class="elusive-icon rss">Subscribe in a reader</a></li>
</ul>
<footer class="site-footer clearfix">
<section class="copyright"><a href="https://blog.pragmaticengineer.com">The Pragmatic Engineer</a> &copy; 2024</section>
</footer>
</aside>
<aside class="read-next">
<a class="read-next-story " style="background-image: url(https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/03/IMG_0989-1.jpg)" href="/the-10x-engineer-evolution/">
<section class="post">
<h2>The “10x engineer:&quot; 50 years ago and now</h2>
<p>How has parts of the classic book on software engineering, ‘The Mythical Man Month,’ aged with time, and is it still relevant half a century on – or does it belong in a museum, alongside floppy discs?&hellip;</p>
</section>
</a>
<a class="read-next-story prev " style="background-image: url(https://storage.ghost.io/c/39/f8/39f85cc7-8637-40fc-a57c-f45754453717/content/images/2024/01/Screenshot-2024-01-04-at-21.17.27-1.png)" href="/section-174/">
<section class="post">
<h2>The Pulse: Will US companies hire fewer engineers due to Section 174?</h2>
<p>It’s rare that a tax change causes panic across the tech industry, but it’s happening in the US. If Section 174 tax changes stay, the US will be one of the least desirable countries to launch startups&hellip;</p>
</section>
</a>
</aside>
<!-- Signup move up -->
<script>
let contentParent = document.getElementById("content");
let newsletterWithFormElement = document.getElementById("newsletter");
let newsletterWithoutFormElement = document.getElementById("newsletter-second");
let newsLetterTargetPosition = getLastElementBeforeSpecificNode(contentParent.children, "H2", 2); // Add after the 2nd h2
if(contentParent.children.length > newsLetterTargetPosition) {
let nextSibling = contentParent.children[newsLetterTargetPosition];
contentParent.insertBefore(newsletterWithoutFormElement, nextSibling);
} else {
newsletterWithoutFormElement.style.display = "none"
}
function getLastElementBeforeSpecificNode(nodes, nodeName, numberOfNodesToPass) {
var numberOfSpecificNodessSeen = 0;
for(let i=0;i<nodes.length; i++) {
if(nodes[i].nodeName == nodeName) {
numberOfSpecificNodessSeen += 1;
}
if(numberOfSpecificNodessSeen == numberOfNodesToPass+1) {
if(i > 0) {
return i;
} else {
return nodes.lenght;
}
}
}
}
</script>
</div>
<!-- Geniuslink -->
<!--
<script type="text/javascript" src="//cdn.geni.us/snippet.min.js" defer></script>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
var tsid =116191;
Genius.amazon.addOnClickRedirect(tsid, false, "https://buy.geni.us"); });
</script>-->
<!-- Google Analytics -->
<!--
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-7745037-4', 'auto');
ga('send', 'pageview');
</script>
-->
<!-- Plausible -->
<script async defer data-domain="blog.pragmaticengineer.com" src="https://plausible.io/js/plausible.js"></script>
<!-- Source code higlighting -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/components/prism-javascript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/components/prism-css.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://blog.pragmaticengineer.com/assets/js/jquery.fitvids.js?v=z1Nmfc9MKQxCtlIV"></script>
<script type="text/javascript" src="https://blog.pragmaticengineer.com/assets/js/index.js?v=wmn33DUYd3qPYenJ"></script>
</body>
</html>