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.

1
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:

1
$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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

This site uses Akismet to reduce spam. Learn how your comment data is processed.