Rendering ASP.NET UTC time as local time of the browsers time zone

by Klaus Graefensteiner 5/13/2008 1:16:20 AM

Introduction

It is a common practice to store time as UTC on the server and render it as local time based on the time zone the browser is running in. This blog post describes one simple approach to solving this problem.

Napkin drawing illustrating time offset transformation

Figure 1: Napkin drawing illustrating time offset transformation

Problem

I came across this problem when I was re-designing the time stamp handling of my BlogEngine.NET ASP.NET application. I changed it to store time stamps in UTC time. One challenge now was to render the time when the posts were published in the local time of the browser. Besides that I needed a solution for editing the time as local time and then posting it back as UTC time to the ASP.NET page on the server (see Figure 1).

Design

Render local time

My approach is to convert the .NET DateTime object to a string and pass this string to a ASP.NET Textbox control. When the page is loading, the onload event runs a JavaScript that uses the Textbox string to construct a Date object. This JavaScript Date object represents the passed in time stamp as local time. The script then overwrites the original UTC time string with the local time string.

Post back UTC time

A user can now change the time string in the Textbox control in the browser and then submit the change to the server. The submit action will now trigger another JavaScript that now constructs a Date object in UTC time, converts it to a string and sets a hidden input element with the new time string. This string will be parsed on the server and the ASP.NET DateTime object that originally provided the time stamp will be updated.

Solution

I created a VS 2005 demo web site that has one page. This page contains an ASP.NET Textbox control, a hidden input control, a ASP.NET Button control and a ASP.NET Label control.

The page looks like this:

Web page demonstrating the UTC time conversion live

Figure 2: Web page demonstrating the UTC time conversion live

ASP.NET markup

   1: <body onload="ElementStringToLocalTime('TextBox1')">
   2:     <form id="form1" runat="server" >
   3:         <div>
   4:             <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>&nbsp;
   5:             <br />
   6:             <input type="hidden" runat="server" id="Hidden1" />
   7:             <br />
   8:             <asp:Button ID="Save" runat="server" Text="Save" OnClick="Save_Click" />
   9:             <br />
  10:             <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
  11:         </div>
  12:     </form>
  13: </body>

Code behind file

   1: using System;
   2: using System.Data;
   3: using System.Configuration;
   4: using System.Web;
   5: using System.Web.Security;
   6: using System.Web.UI;
   7: using System.Web.UI.WebControls;
   8: using System.Web.UI.WebControls.WebParts;
   9: using System.Web.UI.HtmlControls;
  10:  
  11: public partial class _Default : System.Web.UI.Page 
  12: {
  13:     private DateTime TimeStore = new DateTime();
  14:     
  15:     protected void Page_Load(object sender, EventArgs e)
  16:     {
  17:         if (!Page.IsPostBack && !Page.IsCallback)
  18:         {
  19:             string timeString = DateTime.UtcNow.ToString("yyyy-MM-dd HH\\:mm");
  20:             TextBox1.Text = timeString;
  21:             Label1.Text = "";
  22:             Save.Attributes.Add("onclick", "CopyElementToUTCTimeElement('TextBox1', 'Hidden1')");
  23:         }
  24:     }
  25:     
  26:     protected void Save_Click(object sender, EventArgs e)
  27:     {
  28:         TimeStore = DateTime.ParseExact(Hidden1.Value, "yyyy-MM-dd HH\\:mm", null);
  29:         Label1.Text = TimeStore.ToLongTimeString();
  30:         TextBox1.Text = TimeStore.ToString("yyyy-MM-dd HH\\:mm");
  31:     }
  32: }

JavaScript

   1: function ElementStringToLocalTime(elementID)
   2: {
   3:   var element = document.getElementById(elementID);
   4:   var timeString = element.value;
   5:                               
   6:   var utcTime = new Date();
   7:   utcTime = ParseTimeStringAsUTCTime(timeString);
   8:   
   9:   element.value = FormatTime(utcTime);
  10: }
  11:  
  12: function CopyElementToUTCTimeElement(sourceElementID, destinationElementID)
  13: {
  14:   var SourceElement = document.getElementById(sourceElementID);
  15:   var DestinationElement = document.getElementById(destinationElementID);
  16:  
  17:   var timeString = SourceElement.value;
  18:                               
  19:   var Time = new Date();
  20:   Time = ParseTimeStringAsLocalTime(timeString);
  21:   DestinationElement.value = FormatUTCTime(Time); 
  22: }
  23:  
  24: function AddLeadingZero(num)
  25: {
  26:   if( num < 10)
  27:   {
  28:     return '0' + num;
  29:   }
  30:   return num;
  31: }
  32:  
  33: function FormatTime(time)
  34: {
  35:  //returns string from a Date object in the following format "2008-05-07 21:15"
  36:   return time.getFullYear() + '-' + AddLeadingZero(time.getMonth()) + '-' + AddLeadingZero(time.getDate()) + ' ' + AddLeadingZero(time.getHours()) + ':' + AddLeadingZero(time.getMinutes());
  37: }
  38:  
  39: function FormatUTCTime(time)
  40: {
  41:   //returns string from a Date object in the following format "2008-05-07 21:15"
  42:   return time.getUTCFullYear() + '-' + AddLeadingZero(time.getUTCMonth()) + '-' + AddLeadingZero(time.getUTCDate()) + ' ' + AddLeadingZero(time.getUTCHours()) + ':' + AddLeadingZero(time.getUTCMinutes());
  43: }
  44:  
  45: function ParseTimeStringAsLocalTime(timeString)
  46: {
  47:   //creates Date object based on string in the following format "2008-05-07 21:15"
  48:   var numYear = parseInt(timeString.substring(0,4), 10);
  49:   var numMonth = parseInt(timeString.substring(5,7),10);
  50:   var numDay = parseInt(timeString.substring(8,10), 10);
  51:   var numHour = parseInt(timeString.substring(11,13),10);
  52:   var numMinute = parseInt(timeString.substring(14,16),10);
  53:   var Time = new Date(numYear, numMonth, numDay, numHour, numMinute, 0, 0);
  54:   return Time;
  55: }
  56:  
  57: function ParseTimeStringAsUTCTime(timeString)
  58: {
  59:   //creates Date object based on string in the following format "2008-05-07 21:15"
  60:   var numYear = parseInt(timeString.substring(0,4), 10);
  61:   var numMonth = parseInt(timeString.substring(5,7),10);
  62:   var numDay = parseInt(timeString.substring(8,10), 10);
  63:   var numHour = parseInt(timeString.substring(11,13),10);
  64:   var numMinute = parseInt(timeString.substring(14,16),10);
  65:   
  66:   var utcTime = new Date();
  67:   
  68:   utcTime.setUTCFullYear(numYear);
  69:   utcTime.setUTCMonth(numMonth);
  70:   utcTime.setUTCDate(numDay);
  71:   utcTime.setUTCHours(numHour);
  72:   utcTime.setUTCMinutes(numMinute);
  73:   utcTime.setUTCSeconds(0);
  74:   utcTime.setUTCMilliseconds(0);
  75:   return utcTime;
  76: }

Download

The sample Visual Studio 2005 web site solution can be downloaded here: UTCDemo.zip

Ausblick

The functionality demonstrated here is a good candidate for encapsulation as ASP.NET control. One property of this control could be a format string that specifies how the time string is passed between ASP.NET and JavaScript.

kick it on DotNetKicks.com

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

BlogEngine.NET

Related posts

Comments

6/18/2008 2:12:03 AM

dotnet

Thanks for sharing TimeZone Calculation Information, this would also be helpful dotnetguts.blogspot.com/.../...nd-timespan-in.html

dotnet us

Comments are closed

Powered by BlogEngine.NET 1.3.0.0
Vanilla Theme by Klaus Graefensteiner

About Klaus Graefensteiner

GRAVATAR icon of Klaus Graefensteiner I enjoy the programming of machines.

E-mail me Send mail
Blogroll as OPML OPML LinkedIn Profile View Klaus Graefensteiner's LinkedIn profile

Calendar

<<  September 2008  >>
MoTuWeThFrSaSu
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

View posts in large calendar

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Sign in