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.