Wednesday, 6 July 2011

Setting your website DateTime according to Time Zone Offset of the client



Time zone of countries is different and to deal with it while developing a website is a big headache. We have seen situations where we have to use the GMT time and get the time zone of client to show every user his own Date Time. Recently I was working on website project and I face this problem and I solved it so thought of writing an article on how to implement this.  Let's start with it.

First of all to get the client TimeZoneOffset you need JavaScript code. 

<script type="text/javascript">
        // Original script by Josh Fraser (http://www.onlineaspect.com)
        // Some customization applied in this script code
        var minutes;
        function calculate_time_zone() {
            var rightNow = new Date();
            var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);  // jan 1st
            var june1 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0); // june 1st
            var temp = jan1.toGMTString();
            var jan2 = new Date(temp.substring(0, temp.lastIndexOf(" ") - 1));
            temp = june1.toGMTString();
            var june2 = new Date(temp.substring(0, temp.lastIndexOf(" ") - 1));
            var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60);
            var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60);
            var dst;
            if (std_time_offset == daylight_time_offset) {
                dst = "0"; // daylight savings time is NOT observed
            } else {
                // positive is southern, negative is northern hemisphere
                var hemisphere = std_time_offset - daylight_time_offset;
                if (hemisphere >= 0)
                    std_time_offset = daylight_time_offset;
                dst = "1"; // daylight savings time is observed
            }
            var i;
    // Here set the value of hidden field to the ClientTimeZone.
                         minutes = convert(std_time_offset);
            TimeField = document.getElementById("HiddenFieldClientTime");
            TimeField.value = minutes;
            alert('your time zone is ' + minutes);      
        }
        // This function is to convert the timezoneoffset to Standard format
        function convert(value) {
            var hours = parseInt(value);
            value -= parseInt(value);
            value *= 60;
            var mins = parseInt(value);
            value -= parseInt(value);
            value *= 60;
            var secs = parseInt(value);
            var display_hours = hours;
            // handle GMT case (00:00)
            if (hours == 0) {
                display_hours = "00";
            } else if (hours > 0) {
                // add a plus sign and perhaps an extra 0
                display_hours = (hours < 10) ? "+0" + hours : "+" + hours;
            } else {
                // add an extra 0 if needed
                display_hours = (hours > -10) ? "-0" + Math.abs(hours) : hours;
            }
            mins = (mins < 10) ? "0" + mins : mins;
            return display_hours + ":" + mins;
        }
        // Adding the funtion to onload event of document object
        onload = calculate_time_zone;
</script>

This code will give you client time zone offset in standard format. And also you don't have to worry about the DayLightTime saving problem. The javascript code will take care of it.

To use the TimeZoneOffset to get the client time you have to save in GMT time format. So while saving current DateTime into database always use DateTime.UtcNow instead of DateTime.Now

Call the function pass the datetime you want to change according to client time zone offset

using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
/// <summary>
    /// Method takes Date as string. and the client timezoneoffset as object
    /// </summary>
    /// <param name="date"></param>
    /// <param name="O"></param>
    /// <returns></returns>
        public static DateTime getClientTime(string date, object ClientTimeZoneoffset)
        {
            if (ClientTimeZoneoffset != null)
            {
                string Temp = ClientTimeZoneoffset.ToString().Trim();
                if (!Temp.Contains("+") && !Temp.Contains("-"))
                {
                    Temp = Temp.Insert(0, "+");
                }
       //Retrieve all system time zones available into a collection
                ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
                DateTime startTime = DateTime.Parse(date);
                DateTime _now = DateTime.Parse(date);
                foreach (TimeZoneInfo timeZoneInfo in timeZones)
                {
                    if (timeZoneInfo.ToString().Contains(Temp))
                    {
                        TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(timeZoneInfo.Id);
                        _now = TimeZoneInfo.ConvertTime(startTime, TimeZoneInfo.Utc, tst);
                        break;
                    }
                }
                return _now;
            }
            else
                return DateTime.Parse(date);
        }

Calling this function to convert the server time to client time and display it in the TextBox.

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack == true)
    {
        if (String.IsNullOrEmpty(HiddenFieldClientTime.Value) == false)
        {
            string Temp = HiddenFieldClientTime.Value;
            // call the method to convert the utc now time to client time
            TextBox1.Text = getClientTime(DateTime.UtcNow.ToString(),     Temp).ToString();
        }
    }
}

Here is the code for  .aspx page:

<body>
  <form id="form1" runat="server">
    <div>
        <asp:HiddenField ID="HiddenFieldClientTime" runat="server" />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Button" />
    </div>
    </form>
</body>