Time is fascinating. Maybe it's because I entered the field right before Y2K, but how we've taught computers to deal with time has been an area of interest for much of my career. Over a decade ago I gave a talk at HVOpen on this, and in recent years realized the core content never made it to the internet. It was one of my favorite talks, and unlike a lot of tech talks, still really is relevant 11 years later.

So here it is, from the archive, so it will be part of the internet core going forward. When I first gave this talk I did it with a 5th Doctor scarf on (until it got too hot in that room at Vassar). Read on if you want to learn more about time itself.

<div class="slides">

Title slide: "When will then be now? Soon." by Sean Dague (dague.net, @sdague), with a photo of the Long Now Foundation's 10,000-year clock mechanismThis is the clock of the Long Now. It's a clock designed to run 10,000 years, without human intervention. It's intended to end up in the hills of Nevada. It's a whole other story about that clock, but it felt like a good visual to kick us off.

Falsehoods programmers believe about time (page 1): A two-column list including: there are always 24 hours in a day; months have 30 or 31 days; years have 365 days; February is always 28 days; any 24-hour period begins and ends in the same day; a week always begins and ends in the same month; a week always begins and ends in the same year; the machine a program runs on will always be in the GMT time zone; time zones will never change in production; the system clock will always be set to the correct local time; the system clock will always be set to a time not wildly different from correct; if incorrect, the clock will be off by a consistent number of seconds; the server and client clock will always be set to the same time; the server and client clock will be set to around the same time; the time on the server and client clock would never differ by decades. Source: infiniteundo.comFalsehoods programmers believe about time (page 2): Continuing the list: if server and client clocks are not in sync, they will at least be out of sync by a consistent number of seconds; the server and client will use the same time zone; the system clock will never be set to a time in the distant past or far future; time has no beginning and no end; one minute on the system clock has exactly the same duration as one minute on any other clock; ok, but the duration will be pretty close; fine, but one minute on the system clock would never be more than an hour; you can't be serious. Right column: the smallest unit of time is one second; ok, one millisecond; it will never be necessary to set system time to any value other than the correct local time; ok, testing might require it but never in production; time stamps will always be in a commonly-understood format like 1339972628; time stamps will always be in the same format; time stamps will always have the same level of precision; a time stamp of sufficient precision can safely be considered unique; a timestamp represents the time an event actually occurred; human-readable dates can be in universally understood formats such as 05/07/11. Source: infiniteundo.comWhen I first came across this list, I nearly died laughing. The original content is still up, and even has a citable reference now. It is really worth spending time reading the whole thing, and some of the other ones that inspired it.

Why is time hard?

Why is time hard in software: bullet points — the physical world is messy and variable; the Earth is round; time is stored in fixed storage containers (ints / fixed record fields); humans expect context-appropriate representationsThis gets to the crux of why I find this whole area fascinating. Time and software is a classic case of where your beautiful abstractions a ground down by that messy inconvenience of the world not really working that way. That interface between real world problems and digital approximations, and how we make it work, is the core of what software engineer is in my mind.

We live on this oblate sphereoid rock, that's spinning tilted, while whipping through space. The most natural concept that comes out of this is one rotation, a day. Except because of the tilt of the Earth, that doesn't even have the courtesy of being the same day over day!

What is a day? Bullet points: well, it depends on what kind of day. Sidereal Day (2): 23:59:04 = mean sidereal day. Solar Day (3): 23:59:39–24:00:29 in length (September days shorter than December days based on eccentricity of Earth orbit); 24:00:00 = mean solar day. Also gets longer by 2.3ms per 100 years; current definition of second is from 1967. Diagram showing Earth positions labeled 1, 2, 3 in orbit with the Sun (yellow circle) illustrating the difference between sidereal and solar days.What even is a day!

This is a great question to pose to an audience that thinks they know the answer. It's when the sun comes up, it's when we pass midnight (also, how do you know when you pass midnight? under older time systems the day started a noon for this reason). But it seems like the simplest question that we should all know, and yet, it's more complicated.

Also, we have this pesky problem that a day changes in length over time because the moon is slowing us down, and slowly getting further away at the same time. (Which has the interesting consequence that total solar eclipses will eventually not happen any more.)

Why does this keep changing? Diagram titled "How ocean friction causes the moon to recede" showing Earth with tidal bulges misaligned from the Earth-moon line due to rotation, with arrows explaining how Moon's gravity slows Earth's rotation and ocean/crust friction causes the Moon to recede. Right column: long term trend = +2ms per century; medium term trend = continent shifting; short term trends = weather, earthquakes, melting icecaps all change moment of inertia. Footer references what-if.xkcd.com/26.## Patching Time

Ok, so how do we fix all these messy things about time not being nice and digital. Through lots of conditionals and exceptions.

Leap Years: Why? Keep the solstices at approximately the same time of year. Length of a year: Old Roman Calendar 365 days; Julian Calendar 365.25 days; Gregorian Calendar 365.2425 days; Actually 365.2422074 (365 days, 5 hrs, 48 mins, 46 seconds). When do we have a leap year? if (year % 4 == 0) and (not (year % 100 == 0) or (year % 400 == 0))Leap years at the one everyone knows about. There are not 365 days in a year. It's a little more. But it's not exactly 1 every 4 years. Very few people know the actual formula (I can be so much fun at parties). It's only slightly less obscure than the formula for Easter.

The most interesting ramification of the leap year formula is that years divisible by 100 are not leap years, but those by 400 are. 2000 was a leap year because of clause 3. 2100 will not be.

2100 is an extreme edge test condition. Every piece of software ever written has not been field tested on a year like 2100. I am sure that most implementations of leap years don't include rule 2 and 3, because it didn't have to. When 2100 hits it's going to be a very interesting kind of mess.

Solstice Drift Adjustments: Chart titled "Leap shifting of the Gregorian calendar — Date of summer solstice over 400 years" showing the date of the June solstice (y-axis, June 20–23) from 1750 to 2250. The date drifts downward across each 100-year cycle and then resets sharply upward at century marks due to the leap year skipping rule, forming a sawtooth pattern. Source: Wikipedia/Leap_yearThis graph is a wonderful visualization of how the timing of the solstice moves over hundreds of years, and why we need that complicated adjustment. Also why rule 3 needs to be there, otherwise we drift.

Leap Days: When do we insert a leap day? Clearly at the logical place at the end of the year… oh wait. Why Feb? Also, has the following ever bothered you: Sept = 9, Oct = 10, Nov = 11, Dec = 12Cool, so we're good with leap year,s, it's a patch. So lets slap a day on the end of the year and be done with it.

So, we add it to Feb.... WAT. Funny story, that used to be the last month of the calendar. A curious person might be wondering why we have months that sound like 7, 8, 9, 10, but are numbered 9, 10, 11, 12. Those are exactly the kinds of messy failed abstractions, and cultural archaeology, that I find interesting. They give us hints as to past decision making.

When does the year start? Bullet points: do months have to nicely fit into years? Weeks don't nicely fit into months. Transition to Gregorian Calendar became a good synchronizing point. For centuries there was dual dating in Europe: 10/21 February 1750/51. Table showing when different countries adopted January 1 as New Year: Grand Duchy of Lithuania 1362, Venice 1522, Sweden 1529, Holy Roman Empire 1544, Spain/Portugal/Poland 1556, Prussia/Denmark/Norway 1559, France 1564, Southern Netherlands 1576, Lorraine 1579, Dutch Republic 1583, Scotland 1600, Russia 1700, Tuscany 1721, Britain/Ireland/British Empire (except Scotland) 1752, Greece 1923, Turkey 1926, Thailand 1941The fact months are weird shaped, some are 10% shorter than others (which I need to constantly point out when Product folks say things like "let's do the easy thing and give them X per month"), weeks are a bundle of days that don't fit into months. Also, we had this whole problem of accounting leap years wrong for over 1000 years, that needed fixing.

The biggest software patch rollout in the history of humanity, synchronizing the year, took over 500 years. It required the adoption of a new Calendar. And when that new Calendar was adopted most governments switched the beginning of the year to Jan 1 at the same time. But it did mean over centuries you ended up with dual dating of events in Europe using both the new & old days, and new and old years (for Jan/Feb).

Calendar for the year 1752, showing all 12 months. September is notably short — days 3 through 13 are missing, skipping from September 2 directly to September 14, reflecting Britain's transition from the Julian to the Gregorian calendar.The standard UNIX tool cal... has this in there! It's such a neat and unrequired level of accuracy for almost all tasks, but I salute the software engineer that wanted to make this correct in the event someone needed to calculate the number of days in 1752.

Leap Seconds: UTC defines a day as exactly 86400 SI seconds — except it's not. GMT based on Sun over Greenwich each day — turns out this is hard to be accurate. UT1 is like GMT except using quasars (like GPS does). Attempt to keep UTC within 0.9s of UT1. Graph showing the difference between UT1 and UTC (DUT1) from 1985 to 2015, oscillating between -0.8 and +0.8 seconds, with sharp vertical resets each time a leap second is inserted.So, we have the big patch. Leap days, but it also is inconvenient that the day isn't actually 86400 SI seconds. Why? Because we've gotten so good and so accurate at measuring time, we can now see those fluctuations. The Earth is this big crazy messy thing. Water evaporates, moves around in cloud systems, changes rotational speeds when that happens. Earth quakes jump us around a bit. And in general the second we standardized is just a little too short, and it drifts down over time.

Leap Seconds (continued): Can be positive or negative. Can be at end of December… or June. Are inserted at 23:59:59 UTC. 25 leap seconds on record. …are a terrible idea. See Linux leap second Java bug: lwn.net/Articles/504744/. Google doesn't use leap seconds: googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.htmlLeap seconds can be positive or negative by the spec. As the entire full consequence of long term shift wasn't understood, you need to give yourself freedom of movement (this might become important soon). Leap seconds can be in Dec or Jun, they are inserted at UTC time, because you need them to happen everwhere all at once, which means leap seconds happen at 7 or 8 pm in the US.

It's so complicated to get right, and as a thing that only happens every few years, is easy to get regressions between field tests, there is a lot of push to eliminated it.

Update (2026): climate change and leap seconds. The melting of the ice caps is changing the rate of speed of the earth, slowing it down (mass is shifting from poles to the equator). So we either need to eliminate leap seconds or start doing negative ones.

Leap Second GraphAnd here is the part where software and time really collide. Yes, negative leap seconds are in the spec. But no one implements software to spec. They implement it to working to ship, and then it's out the door. Much like the 2100 leap day bug, a negative leap second probably causes major challenges with worldwide communication systems.

When does time Begin?

Computers count things. And to count anything you need to know where 0 is. Surely this is a well understood? Surely we've all picked reasonable starting points? Surely there is general agreement?

Yeah, well, no. The table below gives you many of the fun options different systems have chosen for counting. The Unix Epoch is probably the most well know of these for anyone in tech. If you've ever seen Dec 31, 1969 show up somewhere oddly, that's a consequence of an uninitialized UNIX time.

Table of epoch dates used in computing: January 1, 0 (Symbian, Turbo DB); January 1, 1 (Microsoft .NET, Go, REXX, Dershowitz/Reingold source code); January 1, 1601 (NTFS, COBOL, Win32/Win64); December 28, 1800 (Clarion); December 31, 1840 (MUMPS); November 17, 1858 (VMS, US Naval Observatory, DVB); December 30, 1899 (Microsoft COM DATE, Object Pascal, LibreOffice Calc); January 0, 1900 (Microsoft Excel); January 1, 1900 (NTP, IBM CICS, Mathematica, RISC OS, Common Lisp, Michigan Terminal System); January 1, 1904 (LabVIEW, Apple Mac OS through v9, Palm OS, MP4); January 1, 1950 (SEGA Dreamcast, Sintran_III); January 1, 1960 (S-Plus, SAS); December 31, 1967 (Pick OS, iBase, Universe, Unidata, Revelation, Reality); January 1, 1970 (Unix, C, Java, JavaScript, Perl, PHP, Python, Ruby, Tcl, ActionScript); January 1, 1978 (AmigaOS); January 1, 1980 (IBM BIOS, DOS, OS/2, FAT12–FAT32); January 6, 1980 (Qualcomm BREW, GPS, ATSC); January 1, 1981 (Acorn NetFS); January 1, 1984 (CIA CAN automation TIME_STAMP); August 22, 1999 (Galileo satellite); January 1, 2000 (AppleSingle, AppleDouble, PostgreSQL, ZigBee UTCTime)I did amateur astronomy for a while. Astronomy has a time system called JD, which is a Julian Day count with 0 a few thousand years ago. Also, the day rolls over at noon. This is incredibly useful to have something that's both this long, and with it's own count that ignores things like years. We have all these historical brightness records of variable stars (lots of stars aren't fixed brightness), and these help us understand stellar phenomenon.

Light Curve for PTF11kly — a multi-color scatter plot showing the brightness (magnitude) of a supernova over time measured in Julian Days (JD), from approximately JD 2,455,800 to 2,455,950. The curve rises sharply to peak brightness around magnitude 10 then fades across multiple color bands (visual, Johnson V, Johnson B, Cousins R, etc.). An arrow points to the x-axis with a note explaining Julian Day Numbers: integer solar days counted from noon GMT on January 1, 4713 BC, with JD 0 = November 24, 4714 BC in the proleptic Gregorian calendar; JD for January 1, 2000 was 2,451,545; Julian date for 00:30:00.0 UT January 1, 2013 is 2,456,293.520833.If time has a beginning, then it must have an end, right? This is especially true given that we encode this in computer fields that have limits.

The most well known of these events was Y2K. But we're about 12 years out now from a big rollover event with Y2K38. That UNIX epoch time was originally stored in a 32bit integer. This size limitation got fixed in Linux over a decade ago, when it moved to 64bit processors. But computer systems last longer than people imagine, so this whole thing is going to be a mess.

More messy, the protocol we use world wide to synchronize clocks has a rollover event in 2036. It was originally unsolved at the time of this presentation, though looks like there is a 64bit solution there now as well.

The End of Time: Jan 4th 1975 — DEC overflow of 12-bit time field. Y2K — text storage of 2-digit dates overflowing. Y2K10 — BCD encodes 0–9 as 0x0–0x9, but BCD encodes 10 as 0x10 whereas hexadecimal encodes 10 as 0x0A; affected SMS (Windows Mobile), PS3, some bank systems. Y2K38 — UNIX used int32 for time; 64-bit Linux uses int64; NTP is still using 32-bit time (rollover happens at 2036 for parity reasons).## Dividing Time

Computers don't feel any special way about time. Humans do. There are hours of the day we expect the sun to be up. We expect the night to be at other times. For the longest time noon was set locally, town by town, based on when the sun was overhead. Big clocks at the center of town would show the time.

When humans moved slow, that was easy. Then we invented trains. They moved pretty quick. But also, to get between places in a predictable way, they needed some kind of time standard. A businessman traveling from NY to Boston couldn't be constantly changing his pocket watch back and forth 7 minutes. And have to forget if his watch was on NY or Boston time.

So time zones were constructed. Binning the world into largely hourly buckets (though not always).

Time Zones: The trains must run on time — but which time? 1884 International Meridian Conference, held in Washington DC, establishes Greenwich as prime meridian. 1918 — US time zones passed, also summer time, which was repealed in 1919.By the very nature of binning time, you end up with anomalies. Places where inside the timezone noon comes too early or too late. Because people like evening hours, the time zones mostly bias that direction, seen in all the red.

World map showing difference between solar time and standard time by country. Most countries are colored in shades of red (UTC ahead of solar time) or green (UTC behind solar time), with Russia and China showing large positive offsets. A color scale at bottom shows the range from -2 to +2 hours difference. Source: Wikipedia, Coordinated Universal Time / Greenwich Mean Time.One would imagine that something as universal as time zones, and as important for computers to get right, would have been a vast international effort. Unless, of course, you work in software, and understand the world looks more like this classic XKCD comic than you really hoped:

xkcd dependency comicHistorical note, this is a tribute to exactly the tz database, Paul Eggert was born in Nebraska.

So two guys that were interested in the problem fully invented computer timezone system, including the naming convention we all use, because they found it interesting. It was a part time thing they did for decades mostly through reading old almanacs. It got embedded in basically every computer in the world.

Eventually they were smart enough to realize their hobby project was such essential infrastructure it needed a succession plan to a standards group. They started that process in 2011. Then a predator VC company that was buying up old Almanacs sued them for copyright violation, threatening to destroy the whole system. Fortunately, this was resolved. But man was that an interesting time to be alive.

And how is this all organized? David Olson (NIH) and Paul Eggert (UCLA) created and maintained tzdata, released under public domain, and invented the Americas/New_York terminology. In 2011 Olson planned to retire and hand off to IANA (RFC 6557). Also in 2011, Astrolabe (an astrology company that had been buying up almanacs) sued Olson/Eggert; the Olson database was pulled from the internet; Astrolabe dropped the suit after EFF intervention. Photo of Paul Eggert.One thing I so appreciate Olson and Eggert for, is they weren't just compiling a list of time zone data. In their source files they have detailed commentary on how they got to the data. And they write this up with a dry wit and wonder. These are some snippets from it. But I've encouraged folks over the years to go to this source and read through it themselves.

Tales from Timezones: Two text excerpts from the tzdata source comments. Left box: notes about Indiana's complex timezone history since 1970 — most counties are America/Indiana/Indianapolis, with various counties using America/Chicago, America/New_York, America/Kentucky/Louisville, or their own histories. Notes that Shanks partitioned Indiana into 345 regions each with its own time zone history. Right boxes: Shanks vs. Howse debate about when Michigan started using standard time (1885 vs Detroit's 1900 city vote story); and a Paul Eggert note about Alaska switching from Julian to Gregorian calendar on 1867-10-18 (Julian) / 1867-10-06 (Gregorian) when the US bought it from Russia. Footer: dague.net/2008/12/30/who-knew-that-timezone-history-could-be-so-compelling/Because of the whole tilt of the earth thing, and the fact that we've established a cultural work day of 9 to 5, as you go further north you run into the issue that in the summer you get a lot of hours of daylight at culturally unuseful times, like 4am.

In the early 20th century lots of countries instituted summer time (aka Daylight Savings Time), to shift that culturally unuseful 4 or 5 am light block into evening at 8pm where it was more useful. The big push here was not Ag (as people get told) but the outdoor recreation industry, baseball and golf.

Lot's of excuses were made on energy savings. It's one of the reasons the US extended summer time by 4 weeks in 2005. Which being the first change in US timezones in 35 years, was ill supported by software. But when it was actually studied because of the deployment of AC so widely in the US, this probably actually used more electricity than it saved.

Lots of countries have abandoned summer time. Lots of people hate it, and want to stop switching. The US did that in the 1970s oil crisis, and people hated it more than switching. So we're probably stuck with it for a while.

Also, remember all of this is political, so often times changes will get made by act of law, that are retroactive! Fun for software systems to catch up.

Summer Time (aka Daylight Savings Time): Theory of energy saving due to reduced electrical lighting. Air conditioning puts a wrinkle in this plan. Offsets changed by law — illustrated with an Ubuntu changelog entry: "Version 2009n-0ubuntu0.9.04.1: Add argentinas-dst-2009.diff: Disable DST switch for Argentina tomorrow, as the Argentina government decided yesterday. Careful planning is boring." Don't forget about the southern hemisphere.World map showing DST usage by country. Blue = DST currently used (North America, Europe, parts of South America and Australia). Orange = DST formerly used (most of Asia, Africa, South America, Russia). Red = DST never used (equatorial Africa, parts of Middle East and Southeast Asia). Source: Wikipedia/Daylight_saving_time## Exchanging Time

As much as I love time, I love calendars. And am hopelessly dependent on them. If it's not on my calendar, it does not exist. My wife and I have a complex google calendar setup that includes different ones for: me, her, school activities, family activities, and... you get the picture. I managed websites where they were fundamentally about posting events, and I wanted to figure out how those nicely, natively, got into people's calendars.

There is an exchange format for calendaring. It's called icalendar. It was invented about 12 seconds before the internet became a thing, so looks so foreign to our world. It was invented by Lotus and Microsoft to exchange meeting invites across their incompatible otherwise system. It is an RFC, so you can read the standard in full.

For years I was the maintainer of the ruby library for this format, which I took over when I was trying to make it so that ruby on rails could correctly send multipart/mime emails that included the calendar representation, so that my email announcements would auto add to people's calendars.

iCalendar: How do we interchange time/data on a network? Between different networks? Between different vendors? Across timezones? Right side shows the header of RFC 2445 (Internet Calendaring and Scheduling Core Object Specification), authored by F. Dawson (Lotus) and D. Stenerson (Microsoft), published November 1998.iCalendar uses fixed record formats with this begin and end markup that feels very mainframe-esqe. Also, because Time Zones were not a standard (see above), you need to inline embed all the logic of your timezones, including how different time shifts, like summer time, are going to work in your timezone.

There is a recurrence rule grammar, so you can express things like every Tuesday, or the 3rd Thursday of the month (or the last (-1) Friday of the month). Basically all the rules you need to compute most major holidays. The recurrence logic is not sufficient to encode Easter, you just have to calculate it yourself.

iCalendar Examples: Two code blocks. Left: a simple VCALENDAR/VEVENT for a "Bastille Day Party" on 1997-07-14, with UID, DTSTAMP, ORGANIZER, DTSTART, DTEND, and SUMMARY fields. Right: a VTIMEZONE block defining US-Eastern with both STANDARD (EST, UTC-5) and DAYLIGHT (EDT, UTC-4) components, each with DTSTART and yearly RRULE recurrence rules.The part that drives me bonkers on the standard is line wrapping, which is so unintuitive. iCalendar has a 75 column width. So if you want to put in large blocks of text you have to do the most bizarre line wrapping I've ever seen. All the software does this, that's why it works to send GMail invites to Outlook. But man is it odd.

WAT! Monospace text block quoting RFC 2445 spec: "The iCalendar object is organized into individual lines of text, called content lines. Content lines are delimited by a line break, which is a CRLF sequence (US-ASCII decimal 13, followed by US-ASCII decimal 10). Lines of text SHOULD NOT be longer than 75 octets, excluding the line break. Long content lines SHOULD be split into a multiple line representations using a line 'folding' technique" — with an example showing a DESCRIPTION field split across multiple lines by inserting CRLF followed by a whitespace character.## Dragons Everywhere

All of this is hard. Especially so given that most of this was made in the late 20th century, before we did this thing like rolling over a century boundary. Perl in the 1990s returned a 2 digit year from it's standard library. Not because it was the last 2 digits, but because it was the number of years since 1900.

Plenty of small websites displayed the year as 19100 on Y2K. There are dragons everywhere, read the docs carefully.

You would think these were solved problems. They are not. In a world where most software is barely working shippable software, you end up with bugs everywhere. Like this fun one based on picking the wrong format string for the year.

These are all solved problems… right? Left: screenshot of a tweet from @tef (Dec 29, 2014): "a single character G instead of Y took down twitter's api because the ISO year starts today — thursday is in january. welcome to computers." The tweet has 737 retweets and 318 favorites. Below it, a Guardian headline: "Twitter kicks Android app users out for five hours due to 2015 date bug." Right: photo of an Android phone showing AccuWeather widget displaying Monday, January 5 — but the forecast bar shows dates starting Fri 1/5, Sat 1/6, Wed 1/7, Thu 1/8, suggesting the week display has a date calculation bug.What I wanted people to take away from all of this was: it's always more complicated than you think. Making complex systems work under vast real world constraints is hard. The real world is not a crystal palace abstraction, it messy, human, political, and needs to bend to cultural expectations.

Time in software is a perfect distillation of that collision. And one that people can often relate to because how important it is in their lives that time works correctly.

Hope you enjoyed! Maybe one day I'll do this as a talk again for a live audience, but until then it's at least out here on the internet.

What have we learned today? Title with a screenshot from South Park showing Kyle, Kenny, and Stan sitting at school desks with blank, overwhelmed expressions — captioned "ASSOCIATED PRESS"</div>