Talking about Timezones
Welcome to the first in a few blog posts I’ve decided to write about the challenges faced in bringing the MCJukebox 2.0 update out into production. It’s focused mainly around challenges as a developer, and in this post, the main talking point is the difficulty in providing accurate time synchronisation.
The reason behind needing all of this was to provide our new “shows” functionality. Users in the game can setup a show and we’ll send timestamps between clients and the server to ensure music is always in sync. As a result, a time offset of just a few seconds could really show to an end user.
Our main objective with this part of the codebase was to get the current time in Javascript, independent of any time-zones, and within a high level of accuracy. When I started out, although I knew dealing with time can be tricky, I really did think this would be as easy as getting the Unix epoch time.
This did indeed solve our first issue, as by using the number of milliseconds since the 1st January 1970 UTC, no matter where you were located on the globe, we wouldn’t need to worry about geographical location. For sure, clocks occasionally go out of sync, but I was under the impression that computers had advanced enough to synchronise time over the internet and prevent this.
For anyone who hasn’t looked into it, computers use a time protocol called NTP. It’s a complicated mathematical system which pings an array of servers in order to get the most accurate timestamp it can at any given point. The problem is, while some computers do this flawlessly, I found that many of MCJukebox’s users either had this disabled by default or that although the feature was enabled, their computer hadn’t ever run the process.
In order to solve this, we’ve made a very basic and less technical protocol which uses just one server and gets a timestamp accurate to a small fraction of a second. Millisecond level accuracy would have been great, but the development effort and infrastructure required meant this just wasn’t worth it, especially considering the use case.
The way it works is quite simple - the web client sends a request to our servers for the current Unix timestamp, and also logs when this request was sent. Our server responds with a timestamp, which is accurate to the nearest millisecond at the time the packet is sent. The web client then works out how long the response took by working out how long has elapsed between sending a request and receiving the response. Dividing this by two gives a rough approximation of how long the response took. This can then be added onto the Unix time to work out roughly where we are now. This is turned into an offset parameter, and we’re good to go.
The system isn’t perfect, and we’ve already run into our first issue. One user had their time offset by a full hour without realising and this caused issues as we weren’t prepared for such huge numbers.
To summarise, if you have assumptions about the environment of your clients, you’ll be wrong. You can’t rely on them for anything, and wherever possible, you’ll need to do work again which could possibly have already been done but might not have been. Allowing 90% of users the full experience isn’t enough.