loading...

DateTime.Now: No, no...

lbugnion profile image Laurent Bugnion ・3 min read

Recently my colleague and friend Donovan Brown was in Switzerland for customer visits and for the DotNet Day conference in Zurich. I took the occasion to spend some time with him and we got to talk (as you would expect) about geeky and "cloudy" stuff.

One topic of discussion (and that was also mentioned by one of the clients) is: What do you need to get ready for the cloud... and one topic was: Timezones!!

What time is it, really?

Because of all the regions we have, it means that your code suddenly has the potential to easily go global :) So here's a fun experiment you can do:

  1. Create a new web application. Here I use Visual Studio to create an ASP.NET Core web application with Razor pages.

  2. In the HTML code, display the local time and the UTC time. In ASP.NET, I can use the following code in the index.cshtml:

<h1>Local time: @DateTime.Now</h1>

<h1>UTC: @DateTime.UtcNow</h1>

In Razor pages, you can call C# code directly from the CSHTML markup, which is very convenient.

  1. Run the application locally. If like me you are based in Western Europe, you should see something like the below (notice the 2 hours difference between local time and UTC). If you are based somewhere else, it will vary, but there are very good chances that the Local time and the UTC time are going to be different (except of course if you happen to be in a timezone where the local time is the same as UTC).

Running the application locally

  1. Now deploy your application to Azure, into the West US region. You can do that from Visual Studio directly, or create an App Service in the Azure Portal and deploy there.

  2. Run the West US application. Now you should see the same time displayed for Local and for UTC.

Running the application in Azure

What?

So that might be a surprise, and in fact I wasn't expecting that when I first did this experiment a few months ago.

What's going on here is that the Azure architects decided to make it easy for people to migrate web applications (App Services) from region to region without changes in code used to calculate time and time differences. So they run all the Azure servers on UTC. On the other hand, this has the disadvantage that you might have to modify your code to take this in account when you migrate from on-premises to the cloud

For example, if I am based in Switzerland and deploy my application to Western Europe (which is based in the Netherlands), I would expect my application to have the exact same DateTime.Now in Azure than locally. And yet...

The morale of the story...

The big learning here is that if you are looking to migrate to the cloud, suddenly timezones become very relevant, but not necessarily in the way that you would imagine. It's not that you need to know where your code will be running. It is that you need to know that these regional questions will be abstracted.

It would be a great idea to prepare yourself to the migration by doing the right thing already now on premises: Do not use DateTime.Now in your code but use DateTime.UtcNow instead and do the conversions where needed. This way you are already abstracting the location of your code, and when you migrate to the cloud and the location becomes irrelevant or unpredictable, your code will continue to work without being affected.

Happy coding

Laurent

Posted on May 28 '19 by:

lbugnion profile

Laurent Bugnion

@lbugnion

Passionate about software, architecture, cloud. Dad. Biker. Drone flyer.

Discussion

markdown guide
 

SPAs made thinking about this problem a lot easier: localisation belongs in the client that runs in the browser. So in the backend (and its APIs) everything is UTC.

But I can relate to your point that it was hard when we were rendering web pages on the server. I actually have a Ruby-on-Rails project in which I had worked on the time-zone-abstracted layer, as well as on the time-zone-respecting layer. UTC belonged in the controllers and database for sure, local time in the views, but my models were a mix of both.

 

That is truth! I use momentjs to forget about time manipulation at all.

 

Yes to be clear I didn't intend to solve any time related issue here, merely wanted to make people aware that Azure servers run in UTC.

 

We can change default timezone in App Service by adding a new setting under Application Settings called WEBSITE_TIME_ZONE.
Acceptable values for this setting can be any of the acceptable values defined in the Windows Registry under the key HKLM\Software\Microsoft\Windows Nt\CurrentVersion\Time Zones.

 

That's correct. Like I mentioned in another comment thread, I was merely using App Service as an example to illustrate that the server is running on UTC, but your comment is very correct and appreciated.

 

Thank you for this interesting thing. But I think it could be a workaround, but not as right "pattern".

 

I am not quite sure what you think is a workaround. The mere fact I want people to be aware of is that Azure servers run in UTC 😊

 

Nice post, particularly on the interesting bit that Azure defaults to UTC.
I would, however, be careful with stating to just use UtcNow and make conversions, as people tend to think of it as a silver bullet, as this post by Jon Skeet points out.

 
 

I would also switch or build all new applications using DateTimeOffset.UtcNow 🙂 in case I would deploy it somewhere else I'd be able to track timezone.

 

Yes there are variations of course. The .net code here was more there to illustrate the point but you are right of course.

 

very good decision by the Azure architects, if you ask me :)
they force you to think about the topic before/so that it does not become a problem later :)