How to Make Working With Time Zones and Azure, Easier
I’m drafting this article on the morning of March 10th, 2019, which is the morning when the United States collectively moves our clocks forward by one hour and makes the switch to daylight saving time (DST). We haven’t always moved to DST on the second Sunday in March. The federal government here has been experimenting over the last 100 years by moving the change date forwards, backwards, and sometimes enforcing no DST standard at all. If that seems confusing, then yes, those of us in I.T. already know how time zones, leap years, and time changes complicate our world and are a constant source of bugs and failures.
The federal Department of Transportation regulates the time zones we use in the U.S. This fact might be surprising, until you know the history of how the railroad industry pioneered the use of time zones in the U.S. Until that happened in the late 1800s, every town maintained their own local time using the sun, which made train schedules difficult to standardize.
These days it is the cloud industry that is standardizing our use of time. Azure, for example, defaults to Coordinated Universal Time (UTC) in every resource and every region. When using UTC, time is still set using a local solar time, but the local solar time of a specific location in the world at 0° longitude.
Azure uses UTC Everywhere
What does it mean, specifically, to say Azure uses UTC by default? Let’s take virtual machines as an example. If you create a virtual machine with the default settings, regardless of the location the machine will boot using UTC as the time zone. You can change the time zone of your virtual machines using an ARM template, or using PowerShell, or by logging in and using the UI, or by going to the command prompt and using the tzutil command. As always with VMs, you have complete control.
App Services are another resource that will default to the UTC time zone. You can change the time zone of an App Service by creating an application setting with the name WEBSITE_TIME_ZONE and setting the value to a Windows time zone identifier, like Eastern Standard Time.
But, not every resource in Azure will allow you to change the time zone. One example is Azure SQL. The time zone restriction can create problems if you want to migrate an existing application to the cloud, and the application relies on the server to generate time stamps in the user’s local time. Applications like this typically use time generating functions with no time zone information, like GETDATE and SYSDATETIME in SQL.
You Should Use UTC Everywhere, Too
Ideally, you’ll be writing applications that internally represent and store all time values in UTC. There are numerous benefits to this approach. For starters, one day it will be easier to move the application into new environments like the cloud. Also, UTC time doesn’t change with the season, so there is no need to worry about clocks moving backwards for daylight saving and throwing off calculations. There’s also the advantage of being able to scale software and virtual hardware around the globe without worrying about moving into new time zones. Think of geo-distributing a web application across multiple datacenters or having a SQL Server instance failover from one datacenter to another datacenter 2 time zones away.
Creating or converting an application to use UTC does require some thought and carefulness. You’ll need to avoid functions like GETDATE and SYSDATETIME and rely on GETUTCDATE and SYSUTCDATETIME instead. This is a good practice, even if you are building a cloud native application that assumes the operating environment uses UTC. In C#, use DateTime.UtcNow instead of DateTime.Now.
If your users are entering time into your application using local time, you’ll need to know each user’s time zone and adjust into UTC using DateTime methods in .NET like ToUniversalTime. It is not enough to store a simple numerical value representing the user’s offset from UTC. Remember daylight saving time will change the offset depending on the time of year and the year itself, so it is best to store the user’s time zone identifier, like Central European Standard Time.
Help is Available
Dates are always tricky, but using quality libraries and best practices can help. An example of a library for .NET developers is Noda Time. Noda Time “helps you think about your data more clearly, and express operations on that data more precisely”. Two articles from Microsoft offering guidance are Choosing between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo, and Converting time between time zones.
Personally, I wish we could fix some date and time issues by eliminating the switch from standard time to DST twice a year. Of course, this requires an act of government, which could be a long time coming.