More articles

How To Work With Coordinated Universal Time (UTC) In C#

Written by
Filed under
Published on
Modified on

Working with Dates in any programming language is normally a pretty straightforward task. You save a date in the database and get on your merry way, and display it whenever the need arrives. If you were looking to save a record with the current date let's say, in C# you would do something like the following:


// [C#]
DateTime theTime = DateTime.Now(); // gets the current time and date
DateTime otherTime = DateTime.Today(); // gets the current date starting at midnight

In the Column Settings tab you would set the default value to the GetDate() pre-defined function in SQL Server and we are done. When the record is created this column will have a default value of the current date and time on the server.

That's how you would normally work with dates anyhow. Sometimes, however, that isn't enough.

DateTime.Now() will return the current time that the server is currently set to. The same goes for SQL Server's GetDate() function. Sometimes that's not really a big deal. For example, news publish times, or comment dates. So what if they're off by a few hours to some users. (he's so negative [Jim Gaffigan voice]) Other times, they could be more important values, like a sale order time or activity tracking on your website. When looking for solutions to this issue, I mainly got server side answers. Everything was based on the local time relative to the server's timezone. Personally, I'm not concerned where my server is, just that it stays up and running. Sometimes server's change too. One minute it could be in New York, and the next somewhere overseas.

So What Is UTC

UTC (or Coordinated Universal Time for long) is the time standard that the whole world uses to regulate its clocks. Sounds pretty awesome, I know. Parts of the world are split into their own time zones, for business, commercial, and legal reasons and each time zone is an offset of the UTC time. For example, I live in California, which uses the Pacific Timezone which is -8 hours offset from UTC. You might also need to account for Daily Savings Time, if applicable. Some states do not observe it. Most of Arizona doesn't for example, except for the Navajo Nation. For the sake of brevity and my sanity, I will just cover the basics on how to handle UTC. Just remember that "everything that happens now, is happening now". So time isn't as simple as saving "my" current time and showing it to someone in the world, unfortunately.

The Problem

Unless you're on Ubuntu, you can't set the server time to be represented in UTC, without some nifty tweaks to the Windows Registry. And let's assume for the scenario we don't have access to the registry. Let's say I have a blog (which...I do.. :/) I write posts, and each post is given a publish date. My shared hosting server is in New York and I have a reader in Wyoming.

ME
Pacific Time Zone (UTC-08:00)
Published at 8pm. (I wish)
READER
Mountain Time Zone (UTC-07:00)
Sees it at 9pm
SERVER
Eastern Time Zone (UTC-05:00)
Saved at 11pm

a picture is worth a thousand words :]

Stored using your run of the mill GetDate() function, my reader and I would see that my post was published at 11 pm (New York Time) even though it is 8 pm for me and 9 am for them. And if we store it in UTC time, we'd both see that it was published at 4 am, since our offset is -8 hours. So how do we display to everyone the correct data based on their locations in the world?

Tackling The Problem

The answer is to always save the date in UTC format and worry about the display logic afterward. By knowing the UTC time, we can always work our way to the correctly formatted time for anyone in the world. Both SQL Server and .NET have functions for just this type of situation:


//[C#]
//Any of these functions will return you the UTC time
DateTime time = DateTime.Now.ToUniversalTime(); // sets a DateTime object to the current UTC time
DateTime time2 = DateTime.UtcNow; // same as above
DateTime time3 = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now); // problem with this one is that it will use the //local timezone of the server to calculate utc

//[sql server]

Lucky for us SQL Server has the function "GetUTCDate()" that returns the current UTC time and the DateTime object in C# does the same. Which takes care of our needs, server side. Client side we are still going to need the user's timezone offset in order to be able to work with it. We can't do this from the server, as it doesn't have that information available to it. A few approaches on this one are as follows:

1. Ask the users for their timezone

Many large websites take this approach. And it's probably the simplest. Along with the user's account, you'd save their timezone. Maybe have a timezone database table, with the offset values. Then you can easily work with all the data you have by offsetting the stored UTC dates on the server itself. Or you can iterate through the Timezone's using:


       // [c#]
        ReadOnlyCollection tz;
        tz = TimeZoneInfo.GetSystemTimeZones(); // returns all timezones on the current local system

        for (int i = 0; i < tz.Count; i++)
        {
            string name = tz[i].StandardName;
            int hours = tz[i].BaseUtcOffset.Hours;
            int minutes = tz[i].BaseUtcOffset.Minutes;

            // some timezones do in fact have minutes associated with them
            // India for example is a UTC offset of 5:45
        }

With stored timezone's for users, we can simply add the appropriate offsets whenever we need the local DateTime. Also note that some offsets do in fact use both hours and minutes, so it would be a good idea to store the offsets in terms of total minutes than in hours.


function DateTime getLocal(hours, minutes)
{
        DateTime local = DateTime.Now.ToUniversalTime().AddHours(hours);
        local.AddMinutes(minutes);
        return local;
}

2. Grab the clients offset using javascript

If we are not inclined to bother users to enter their timezone info, then luckily we can grab it from the browser using javascripts GetTimezoneOffset() function. This does have its challenges however if we want to use that date on the server. We'll have to do some Ajax work in order to send it back to the server and to bind it to that particular user's session.


    // [js]
     var d = new Date()
     var n = d.getTimezoneOffset();

3. Display the date in UTC

And lastly, because this is really just for display purposes, we don't, in fact, need to do anything with the offset on the server. We can simply just display to the user the correct time format and be done with it. We can do that by injecting some JavaScript into our page.


    // [c#]
    // why not inject some js onto the page
    public static string GetLocalDate(string strDate)
    {
        string strResult = string.Format("<script>document.write(new Date('{0:MMMM d, yyyy hh:mm:ss tt} UTC').toLocaleString());</script>", strDate);
        return strResult;
    }

Wherever in your code, you display the date, you will want to replace it with this script. The conversion is handled directly in JavaScript give the appropriate UTC date.

Wherever you have dates displayed on your page, just pass them through this function first in order to convert them to the snippet of JavaScript that does the conversion.

Walter G. is a software engineer, startup co-founder, former CTO of several tech companies and currently teaches programming for a coding bootcamp. He has been blogging for the past 5 years and is an avid BMX rider, bio-hacker and performance enthusiast.

Tags

#C#
If you read this far, then I hope you enjoyed this post and found it useful! Consider adding to my daily coffee intake to continue to provide better and more helpful articles in the future!
Maybe later

Discussion / Comments / Questions

No messages posted yet

Add a comment

Send me your weekly newsletter filled with awesome ideas
Post comment