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

by Klaus Graefensteiner 13. May 2008 02:16

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

Tags: , ,

BlogEngine.NET

Comments

6/18/2008 3:12:03 AM #

dotnet

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

dotnet United States |

1/5/2013 12:53:58 PM #

pingback

Pingback from aspnet.deveronline.com

ASP.Net Time Localization | Asp.Net developed Tutorials | Asp.Net Developed Tutorials

aspnet.deveronline.com |

Comments are closed

About Klaus Graefensteiner

I like the programming of machines.

Add to Google Reader or Homepage

LinkedIn FacebookTwitter View Klaus Graefensteiner's profile on Technorati
Klaus Graefensteiner

Klaus Graefensteiner
works as Developer In Test and is founder of the PowerShell Unit Testing Framework PSUnit. More...

Open Source Projects

PSUnit is a Unit Testing framwork for PowerShell. It is designed for simplicity and hosted by Codeplex.
BlogShell is The tool for lazy developers who like to automate the composition of blog content during the writing of a blog post. It is hosted by CodePlex.

Administration

About

Powered by:
BlogEngine.Net
Version: 1.6.1.0

License:
Creative Commons License

Copyright:
© Copyright 2014, Klaus Graefensteiner.

Disclaimer:
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Theme design:
This blog theme was designed and is copyrighted 2014 by Klaus Graefensteiner

Rendertime:
Page rendered at 11/28/2014 7:17:45 PM (PST Pacific Standard Time UTC DST -7)