Inventing a Datetime Web Service

Recently I wanted to experiment with dates in a JavaScript web app. The JavaScript Date object is a fairly decent tool for working with dates. Unfortunately, it has some annoyances,

Existing Datetime Services

So if I don’t trust the local system time to be precise, where can I get a more accurate time? Surely there are web services out there for it, right? NIST operates time.gov and maybe that has a web API for web applications. I don’t need to be super precise — a web API could never be — just within a couple of seconds.

Turns out there isn’t any such web service, at least not a reliable one. Yahoo used to provide one called getTime, but it’s been shut down. In my searches I also came across this:

It supports JSONP, which is almost exactly what I need. Unfortunately, it’s just a free Google App Engine app, so it’s unavailable most of the time due to being over quota. In fact, at the time of this writing it is down.

I could stand up my own server for the task, but that costs both time and money, so I’m not really interested in doing that. It’s liberating to build web apps that don’t require that I run a server. There are so many nice web APIs out there that do the hard part for me. I can just put my app on GitHub’s free static hosting, like this blog. The biggest obstacle is dealing with the same-origin policy. JSONP isn’t always supported and very few of these APIs support CORS, even though they easily could. This is part of the web that’s still maturing. My personal guess is that WebSockets will end up filling this role rather than CORS.

Deriving a Datetime Service

So I was thinking about how I could get around this. Surely some API out there includes a date in its response and I could just piggyback off that. This is when the lightbulb went off: web servers hand out date strings all the time! It’s a standard HTTP header: Date! Even my own web server does this.

function getServerDate() {
    var xhr = new XMLHttpRequest();
    xhr.open('HEAD', '/?nocache=' + Math.random(), false);
    xhr.send();
    return new Date(xhr.getResponseHeader('Date'));
}

This makes a synchronous XMLHttpRequest to the page’s host, being careful to cache bust so that I’m not handed a stale date. I’m also using a HEAD request to minimize the size of the response. Personally, I trust the server’s clock precision more than the client’s. Here it is in action.

Local: ---
Server: ---

This is probably not too exciting because you should be within a couple of seconds of the server. If you’re feeling ambitious, change your local system time by a few minutes and refresh the page. The server time should still be accurate while your local time is whatever incorrect time you set.

Here’s the code for these clocks:

var Demo = Demo || {};

Demo.setDate = function(id, date) {
    document.getElementById(id).innerHTML = date;
};

Demo.offset = Demo.getServerDate() - Date.now();

setInterval(function() {
    var date = new Date();
    Demo.setDate('time-local', date);
    Demo.setDate('time-server', new Date(Demo.offset + date.valueOf()));
}, 1000 / 15);

You know what? I think this is better than some random datetime web service anyway.

Have a comment on this article? Start a discussion in my public inbox by sending an email to ~skeeto/public-inbox@lists.sr.ht [mailing list etiquette] , or see existing discussions.

null program

Chris Wellons

wellons@nullprogram.com (PGP)
~skeeto/public-inbox@lists.sr.ht (view)