Working with User Local Timezone

Home / Working with User Local Timezone

In an application that I’m currently working on, that deals with Sales data, there are instances when I need to apply date comparisons relative to a user’s local time. This is an interesting problem with which to deal.


Fortunately, in JavaScript, we can get the current user’s browser specific timezone offset.

var offset = new Date().getTimezoneOffset();

In an Angular or jQuery application we can add this offset as a header on every XHR request. In Angular, this could be defined when the application is loaded like so:

$httpProvider.defaults.headers.common['TimezoneOffset'] = new Date().getTimezoneOffset();

Once that piece of code is in place, we will get the offset in the header of every request.

In my case, I have DATE data types stored in a database with no time associated. All dates are considered to be at midnight. The problem is displaying to a user whether that date has passed or not (IE – the “day” has started)). This means the date needs to be treated as though it is in the user’s local time and then comparing.

Upon making a request to the server, in ASP.NET, it is possible to inspect the headers. If the “TimezoneOffset” header is present, it can be used to perform the appropriate timezone conversions.

var startDate = DateTime.Now.Date;
// Default to local server offset in case the header is not present.
var offset = (DateTime.UtcNow - DateTime.Now).TotalMinutes;
                
if (HttpContext.Current.Request.Headers.AllKeys.Any(k => k.Trim().ToLower() == "timezoneoffset"))
{
    offset = int.Parse(headers["timezoneoffset"]);
}

TimeSpan tsOffset = TimeSpan.FromMinutes(-offset);
DateTimeOffset dto = new DateTimeOffset(DateTime.UtcNow).ToOffset(tsOffset);
DateTime userLocalTime = dto.DateTime;

if (userLocalTime >= StartDate)
{
    Console.WriteLine("The day has begun locally");
}

// Convert local times back to UTC
var startUtcTime = DateTime.SpecifyKind(new DateTimeOffset(startDate).ToOffset(tsOffset).UtcDateTime, DateTimeKind.Utc);
DateTime userUtcTime = DateTime.SpecifyKind(new DateTimeOffset(userLocalTime).ToOffset(tsOffset).UtcDateTime, DateTimeKind.Utc);

if (userUtcTime >= startUtcTime)
{
    Console.WriteLine("The day has still begun UTC");
}

In the code snippet above, you can see that I create a “startDate,” but this would be synonymous with a date stored in a database. Using the header value for the timezone offset, a TimeSpan, DateTimeOffset, and, finally, the user’s local time can be derived. The dates can also be converted back to UTC and comparisons are still appropriate. All in all, this is a pretty handy technique for my use case where I display to the user if the specified date from the database is in the past or future.

Leave a Reply