Thursday, March 3, 2011

Tracking a browser’s Time zone Offset in ASP.NET

Just the other day I was required to display a website’s dates in a user’s local time.

The solution I came up with was based on getting the time zone offset from the user’s browser using JavaScript, Storing that value into a cookie, then converting the cookie value to the a number I’m used to working with (i.e. negative hours), then I can convert UTC dates to the user’s local time zone by adding the Offset.

All of this magic happens for me in my website’s base page. (All my pages inherit from my base page)

   1: public class BasePage : System.Web.UI.Page
   2: {
   3:     private const string mTimeZoneCookieName = "TZOS"; // Time zone Offset
   4:  
   5:     protected override void OnPreInit(EventArgs e)
   6:     {
   7:         setCookieForTimezoneOffset();
   8:     }
   9:  
  10:     private void setCookieForTimezoneOffset()
  11:     {
  12:         if (Request.Cookies[mTimeZoneCookieName] == null)
  13:         {
  14:             ClientScript.RegisterStartupScript(GetType(), "Timezone",
  15:             string.Format(
  16:             @"<script language=""javascript"">document.cookie = ""{0}="" + new Date().getTimezoneOffset(); </script>",
  17:             mTimeZoneCookieName));
  18:         }
  19:     }
  20:  
  21:     public int TimezoneOffset
  22:     {
  23:         get
  24:         {
  25:             return getTimezoneOffset();
  26:         }
  27:     }
  28:  
  29:     private int getTimezoneOffset()
  30:     {
  31:         int returnValue;
  32:         returnValue = (Request.Cookies[mTimeZoneCookieName] == null) ? 0 : Convert.ToInt32(Request.Cookies[mTimeZoneCookieName].Value);
  33:         // JavaScript returns 300 if the offset is -5 offset so I convert the number
  34:         return (returnValue / 60) * -1; 
  35:     }
  36: }

The only catch is: The very first time a user loads any page the times will be GMT/UTC after a single postback everything is as right as rain. On way this could be corrected is by tweaking the “Timezone” start up script a bit to force a refresh. (And that’s just one solution, I’m sure you can come up with another.)

I hope that helps someone.

Cheers.