Hacker News new | ask | show | jobs
by Tuna-Fish 1327 days ago
> Unix time should be a steady heartbeat counting up the number of seconds since ...

This is nice and clean, so long as you have exactly one computer. The second there are more than one, and they are talking to each other, their clocks can go out of sync with each other. And they will, because they are physical systems that are imperfect and in general much less precise than you'd expect them to be.

This means that there has to be a way to correct for errors. The best method, that almost everyone who manages a lot of computers converges onto, is to "smear out" any errors, by never discretely changing the time on any machine, but just shortening or lengthening seconds slightly to bring any outliers back to the correct values. And once you have this system, dealing with a leap second using it is the easiest, simplest and least errorprone method.

I do think that there are purposes where local "machine time", which is just a monotonic clock counting upwards from bootup, would make sense. Especially when subsecond accuracy is important. But it should always be clear that there is no way to reliably convert between that and wallclock or calendar time. There are *no* intervals of calendar/wallclock time that reliably convert to any interval of machine time. It is not guaranteed that any wallclock minute contains exactly 60 machine seconds.

2 comments

I think people forget how often computers in the 80’s and 90’s were turned off, keeping track of time with a backup battery, and just how many machines had a dead backup battery and users that didn’t know any better.

I fielded tech support questions from an app that had grown to send email. Every week we got a couple of emails from some time on January 1, 1970, each from a new person, and a whole slew of people whose batteries were on the edge of failing and so their machine was days or months off from reality.

The HTTP 1.0 spec already had a solution for two machines with different ideas of the current date. It’s one of my favorite parts of the spec and I’ve used it a few times in order to avoid having to implement my own time negotiation protocols (or in fact to stop others from doing it).

I don’t think that battery chemistry has changed all that dramatically since that time. It was still a 2032 cell, for machines that have a discrete battery. Instead it’s the clock chip and network time protocols that have gotten more efficient, and we use the machines more consistently. Or at least the machines where time counts matter the most are on all the time.

> The HTTP 1.0 spec already had a solution for two machines with different ideas of the current date.

I can't recall noticing this, and can't seem to find anything about it in[1] - could you elaborate?

[1] https://www.w3.org/Protocols/HTTP/1.0/spec.html#Date

You’ve found it, or very nearly. The very next section is Expires:

> The format is an absolute date and time as defined by HTTP-date in Section 3.3.

The implication is subtle but critical. When the server sends a Date header and an Expires header, you don’t expire the content when the local time exceeds the Expires Header. You expire it at

   LocalTime + (Expires - Date)
That covers not only time zones but also clock drift. When the client is sending data such as a POST, it also sends a Date header. That can account for time zones, clock drift, and to an extent network latency. When you’re legally bound to establish the order of events in a distributed system someone has to be the source of truth, and even when you’re not it’s still good to have for your own purposes. The system of record is the only thing that is running on the same clock as the system of record, so it is the most sensible source of truth.

So when a client sends you a buffer full of dated events, you can (and should) consider the timestamps in the POST body as relative to the Date header, not your local system time. Otherwise someone running on brown power or old school power saving mode will screw up all of the timelines in your data.

> You expire it at LocalTime + (Expires - Date)

Which makes for a wonky mess, and I guess is why Cache-Control did away with the entire thing and just tells you how long the response is fresh.

Not as wonky as you'd think, and 60 minutes means something much different than 12:15. Which can be good and it can be bad, but many of my experiences with TTLs have not been pleasant. 60 minutes, as typically implemented, means some user out there has data that is 1:58 stale and he's yelling at your boss on the phone who is now trying to figure out if he should be passing the favor along.

See also ETags which stop trying to be clever about dates and instead be clever about the contents of the message.

Why I like the Date header is that it works well with REST endpoints that care about time but for whom caching is either not a good idea or is orthogonal.

> Not as wonky as you'd think, and 60 minutes means something much different than 12:15.

The expression you’ve posted is literally a complicated way of writing 60mn, and you specifically wrote that it should not be interpreted as 12:15.

> See also ETags which stop trying to be clever about dates

Etags have unrelated role and semantics. Etags go with last-update, which doesn’t suffer from anywhere near as much from drift because it’s checked by the server, which emitted it.

There was a Cray installation in Japan in the late 80s or early 90s which was reportedly turned off at night to save electric costs.
Applications that are require clock synchronization across multiple machines should be maintaining their own clock anyways, independent of the system clock. NTP for millisecond-order precision, atomic clock time cards for microsecond-order precision.