Open the console in any browser and paste this:
new Intl.DateTimeFormat("en", {
timeZone: "America/New_York",
timeZoneName: "longOffset",
year: "numeric",
month: "numeric",
day: "numeric",
}).format(new Date("1880-01-01T12:00Z"))
You’ll get something like 1/1/1880, GMT-04:56:02.
Not minus five. Minus four hours, fifty-six minutes and two seconds. Your browser, the thing you use to read the news, has an opinion about what time it was in New York a hundred and forty-five years ago, and its opinion has seconds in it.
Change the year to 1884 and it says minus five. Try Chicago in 1880 and you get 5:50:36. Try London in 1840 and it’s one minute and fifteen seconds behind Greenwich, which is a strange thing to say about London until you know why.
Here it is as something you can play with. Pick a city, slide the year:
I had a dozen questions when I first saw this and I’m going to answer them in the order they came. Where do the seconds come from? What happened in 1883? Who wrote all of this down, and why does it live inside a web browser? And then the question that turned out to matter for my own work: if my browser knows all this, why can’t I trust the time it gives me?
Let’s start with noon.
For nearly all of human history, noon was a fact about the sky. It’s the moment the sun is highest, and every town could find it with a stick and a shadow. Set your clock to noon when the shadow is shortest and you have local time: correct for you, and wrong for everyone who isn’t standing next to you.
How wrong? The Earth turns 360 degrees in 24 hours, so it turns one degree every four minutes. Move one degree of longitude west and the sun is highest four minutes later than it was where you started. Move from New York to Chicago, about thirteen and a half degrees, and noon arrives fifty-four minutes later. Every town’s clock disagreed with every other town’s clock by exactly the distance between them, converted at four minutes a degree.
That’s where the seconds come from. New York City sits at about 74 degrees west of Greenwich. Multiply by four and you get 296 minutes, which is 4 hours and 56 minutes, plus a second or two depending on where in the city you measure from. The offset is the longitude. Your browser is telling you where New York is.
Simple enough, right? Here’s the wrinkle.
The number your browser gives isn’t quite the arithmetic. If you do the sum for City Hall you get 4:56:01.5. The browser says 4:56:02, and the reason is written down in the file this all comes from, which we’ll get to properly in a minute. Someone maintaining that file, in 2014, found a note in the Monthly Notices of the Royal Astronomical Society from February 1884, reporting that New York City Hall time had been “3 minutes 58.4 seconds fast of Eastern time” just before the switch. Four hours fifty-six minutes and one point six seconds, measured, in 1884. The file rounds it to the second and that’s what your browser says.
So for most cities in the world, the number you get before standard time is longitude times four, done by a computer. For New York, it’s a Victorian astronomer.
Local time works fine until you build a railway.
A train leaving New York at noon, New York time, arrives in Chicago at some hour that is right by Chicago’s clock and nonsense by New York’s, and every station in between has its own clock too. By the 1870s American railroads were running on a great many different times at once, and the timetables were a kind of fiction. The person who fixed it was a man named William F. Allen, the publisher of a railway guide and the secretary of a body called the General Time Convention, which was the railroads’ way of agreeing with each other.
Allen spent months on a plan. Four zones across the country, an hour apart, every clock inside a zone set to the same time. He presented it on the 11th of April 1883 with the line that “local time would be practically abolished”, which he meant as a selling point. By October nearly every railroad had signed on, and the switch was set for Sunday the 18th of November.
That Sunday as four clocks, at the single instant the new Eastern clocks struck noon:
In New York, the town clock said 12:03:58 when the new one said 12:00. So noon had already happened, by the old clock, and then it happened again, by the new one, four minutes later. Every city on the strip got a second noon that Sunday, a different number of minutes after the first. In Chicago the gap was nine. People called it the day of two noons, and Allen was in New York to hear it. His account, quoted in the file that your browser carries, goes like this: “I heard the bells of St. Paul’s strike on the old time. Four minutes later, obedient to the electrical signal from the Naval Observatory … the time-ball made its rapid descent, the chimes of old Trinity rang twelve measured strokes, and local time was abandoned, probably forever.”
Probably forever. He was right.
The line your browser is reading from for New York:
Zone America/New_York -4:56:02 - LMT 1883 Nov 18 17:00u
-5:00 US E%sT 1920
Read it left to right. New York was at minus 4:56:02, on local mean time, until the 18th of November 1883 at 17:00 universal time, which is noon on the new Eastern clocks. Then it was at minus five, following the US rules, until 1920, when the next line takes over. That first row is the day of two noons, written as data. The bells of St Paul’s are in there, if you know where to look.
The picker again, with the row your browser is reading from beside its answer. Every city has one:
-4:56:02 - LMT 1883 Nov 18 17:00uSo where does that file live, and who keeps it?
It’s called the time zone database, or tzdb, or the Olson database after the man who started it. It’s a set of plain text files, roughly one per continent, and it holds every rule about clocks that anyone has been able to document, for every place on earth, from the invention of standard time to the present, with the local mean time before that. The New York line above is one of thousands.
It was started in the early 1980s by Arthur David Olson, who kept it on a server at the US National Institutes of Health and ran the mailing list where people sent in corrections. It’s been maintained, ever since, by volunteers. The IANA, the body that also hands out IP addresses, describes it exactly that way: “maintained by a community of volunteers, who track changes made by political bodies”. Since 2012 the coordinator has been Paul Eggert, a computer scientist at UCLA, now alongside Tim Parenti, and the mailing list is where a great deal of the world’s knowledge about clocks is argued out, one government decree at a time.
The file is honest about what it is and isn’t. Its own theory document says that pre-standard local time is “modeled as local mean time”, that the relationship to longitude “is not exact”, and, more bluntly, that “many, perhaps most, of the tz database’s pre-1970 and future timestamps are either wrong or misleading”. A lot of the old data, it admits, came from “unreliable sources, often astrology books that lack citations”. The New York seconds are the exception, not the rule: a place where someone found a real measurement. For most of the world before 1970, the seconds are a best guess.
Governments change their minds about clocks constantly. Somewhere in the world, several times a year, a country moves its daylight saving date, or abolishes it, or adopts it, or shifts a border. Each time, someone on the list writes the new rule into the file, and a new release goes out. The JavaScript standard itself, the document that defines what your browser’s Intl is allowed to do, says so in a note: the database “is typically updated between five and ten times per year”, and browsers “are recommended to include updates to the IANA Time Zone Database as soon as possible”.
Your browser can format a date for any time zone because it ships a copy of that file. Not a link to it, a copy, compiled into a compact form and bundled with the browser’s international-text library, which is where the Intl in Intl.DateTimeFormat comes from. When you asked for New York in 1880, nothing left your machine. The lookup happened in a table that was already there, that was there before you ever visited a website, that came down with the browser update you didn’t read the notes for.
Which means every device with a browser on it is carrying the day of two noons, and the bells of St Paul’s, and the 1884 astronomer, and Kolkata’s thirty-six years on Madras time, and every daylight saving decree of every government since, all of it, for four hundred and some places. Chrome will tell you it knows 418 of them. Firefox says 468, because it counts a few more names for the same places. The file is the memory of every noon on earth, and you have a copy in your pocket.
And that copy is only as fresh as your last browser update.
This is the part I ran into myself, building an analytics tool, and it’s the reason I went looking for all of the above.
An analytics script sends events with a timestamp on them. The obvious question is whose clock. The visitor’s device has one, and it’s right there in JavaScript. The server has one, and it’s the moment the event arrived. They ought to agree within a second or so, and mostly they do, and then you look at the data.
Some events arrive from the future. Some arrive from last Tuesday. A phone whose owner set the clock by hand, a laptop that woke from sleep and hasn’t synced yet, a device in a country whose government moved the clocks last week and whose browser hasn’t heard. None of these are rare. They’re a small fraction of everything, which at any real volume means every single day.
What I ended up doing in Lynq, my own tool, was to keep both clocks and never confuse them. Every event carries ts, the client’s time, which is the time the person experienced and is never rewritten, and received_at, the server’s time, which drives anything that has to be in order right now. The daily rollups that feed the charts wait two days before they’re final, because a client timestamp can trail its own arrival by a full day and still be honest. The design note for it is one line: the client clock is the analytics clock, the server clock is the realtime clock, and they are different things.
The scheduling version of the same problem is worse, and it’s the one the update lag turns into a story.
In October 2022, Mexico abolished daylight saving time. The decree was published on the 28th, and the last clock change was set for the 30th. The volunteers had the new rule in the time zone database the same day it was published. Then it had to reach the browsers. Firefox shipped it on the 15th of November, in Firefox 107. Chrome shipped it on the 1st of February 2023, in Chrome 110, two and a half months later. In between, a Chrome user’s browser believed a set of rules that no longer existed.
For Mexico City, that turned out not to matter, by luck: the old rules and the new rules agreed all winter and only parted on the 2nd of April 2023, when the old rules would have sprung forward, and Chrome had shipped by then. For the state of Chihuahua it mattered from day one. Chihuahua had been on a different schedule, and the new law moved it to year-round central time. From the 30th of October, a browser with the old file put Chihuahua’s clock an hour behind where it really was, and anything scheduled for nine in the morning in that browser went out at ten.
Nothing about that browser looked broken. It formatted dates confidently, to the second, from a table that had been true until the week before.
Let’s put the console away.
You started with a number that had seconds in it and no reason to. You now know that the seconds are a longitude, except in New York, where they’re an astronomer. That the day the seconds went away had two noons in it and a man listening to church bells. That the whole thing is written in a text file kept by volunteers who were once sued for it. And that a copy of that file is inside your browser, doing the lookup for you, silently, from a version that is exactly as old as your last update.
A lot of trust is stacked on that last part. A date on a screen looks like a fact. It’s an answer from a table, and the table has a date on it too, and the two dates are almost never the same. Most of the time that’s fine. The table says what the government said, the government hasn’t changed its mind, your device has updated, everyone agrees on noon. But “most of the time” is the phrase that every clock bug lives inside, and the fix isn’t cleverer code. It’s knowing which clock you’re reading, and what it was last told.