Why not to ask the server for its "local time"
There are many horror storries of wasted time and money, hard to find bugs and “but it works on my machine”-type situations that could have been avoided if the programmers simply stopped asking the server for its “local time”.
A local time setting might have made sense back when a server was the size of room and was not connected to the internet. Today… not so much.
A neat thing about the Internet is that you can run web apps on servers all around the globe. You can cheaply buy a virtual server located in for instance Germany or England and they will generally work the same. Developers might write a webapp and deploy it to either of those virtual servers and the software would work the same way. The server never sees daylight from inside the data center and does not care what timezone it is in. It does not really matter.
Problems can arise though, if a server has its timezone set to something other than UTC and the software running on it asks for “local time”. Daylight Saving Time (DST) causes skipped and repeated hours. So a scheduled task might be started twice or not at all if the software refers to “local server time”.
Going to work at midnight to shut down the software and servers
There are people that every autumn are called in for special “going off of DST duty”, where they shut down software and servers in order to avoid problems during the change from DST to standard time. While they normally would go home in the evening and sleep at night, on this date they will be awake during the early morning. They shut down certain pieces of software that are relied on by businesses and governments.
Because they are afraid that Bad Things will happen when the hour between 2:00 and 3:00 repeats itself. If a job is set to start every day at 2:30 it will likely be triggered to be started twice in one hour. So they safely shut down the software beforehand and shut down the servers, wait at least an hour before they can start the servers up again.
This is not a made up story. I know of a big company that does this, and I doubt it is the only one.
I commend the system administrators for doing this in order to avoid problems. But it did not have to be like that if the software was made to be resistant to these kinds of problems.
A local time zone makes sense on a personal computer
My laptop has its timezone set to whereever I happen to be. This makes sense because then it can show me what the time is in my local timezone. And other times such as when a file was created are also shown in that timezone.
On a server though, things are different. The users of the system are not necessarily in the same timezone as the server. And why would they care about the timezone where the server is as long as latency is good enough? It does not make much sense to set a “local” timezone for the server.
The local time setting is a mutable global variable
A local time setting is a global variable that can change. In general global variables are bad. So by default you want to avoid them unless there is a really, really good reason for them.
What to do instead
Whenever you write software and ask the server what time it is right now, do not ask a server for its “local time”. Instead ask for the time in UTC.
If you write software that is not run on servers exclusively controlled by you, somebody can change the local time setting to something other than UTC. But even if you only run the software on your own server and have the good policy of setting their timezone to UTC, why not just have your software ask for UTC in the first place instead of relying on the local time setting?
Getting the time right now for another timezone
If you want to know the time right now for another timezone,
you can get the time right now from the server in UTC. Then
convert it to another timezone. Calendar,
the Elixir datetime library
I designed, has a function that does this for you. For instance to
get the time right now in Copenhagen you can call
Calendar.DateTime.now!("Europe/Copenhagen")
. Behind the scenes
it gets the time right now in UTC and then shifts it to the Copenhagen
timezone. The important thing is that we do not rely on the local time
setting of the server. Instead the code gets the timezone identifier from
somewhere - it could be the webbrowser of a user or a database or a config file.
There is an important difference between asking for a default unspecified local time based on a global variable and instead providing an identifier for a specific timezone in order to get the time right now for that timezone.
When dealing with the daily lives of most people, the time in their various timezones are important. But for internal operations on a server, that are not directly related to those timezones, it makes more sense to use UTC. For instance timestamps of files or timestamps of when a database record was created.
Defaults stacked against programmers
Unfortunately “local time” is sometimes the default in standard libraries.
This is the case with Erlang’s file:read_file_info
that provides information
about when a file was last changed. But by default it returns the time
in local time. So if you want to compare and see how long it has been
since the last file change, you have to get the local
time of the server. But the calculation will be wrong when affected by DST.
From the file module part of the Erlang manual:
The time type returned in atime, mtime and ctime is dependent on the time type set in Opts :: {time, Type}. Type local will return local time, universal will return universal time and posix will return seconds since or before unix time epoch which is 1970-01-01 00:00 UTC. Default is {time, local}."
For this Erlang example you have to pass an extra argument in order to
get the timestamps as UTC. Hopefully in the future library designers
will choose UTC to be the default for these kinds of things.
But for now instead of: file:read_file_info('example.txt')
you have to use file:read_file_info('example.txt', [{time, universal}])
Then you have a UTC timestamp
that you can compare with the time right now in UTC: calendar:universal_time()
instead of calendar:local_time()
.
It is worth it
I encourage developers to avoid asking the server for its “local time” even if it takes passing an extra argument in some places. This practice is not a panacea for all time related problems, but it can eliminate some very nasty bugs. And its widespread use would mean less sysadmins would need to be awake to shut down servers before DST events.
If you liked this post you might want to follow me on twitter for updates on new posts and more. Twitter handle: @laut