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 UTCvar 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.