|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
Introduction
In the web applications we are often displaying date/time values. But how can
we display value according to the user’s time zone?
We can do this by using following steps:
- Get difference in hours between user’s local time and GMT using Java
Script
- Pass this value from client to the server
- Attach this value to the remote user object on the server (for example
attach it to the Profile object)
- Detect actual time zone based on difference between user’s local time
and GMT.
-Calculate time according to the time zone and display time and time
zone
Code samples
web.config:
Configuring storage
of difference between local time and GMT is very simple in asp.net
2.0
....
< profile enabled="true" >
< properties>
< add
name="hoursDiffStdTime"
defaultValue="0" type="double"/>
</ properties>
</ profile>
....
login.aspx:
Here is simple
Javascript to get time difference on the browser.
.....
< head runat="server">
<title>Welcome</title>
<script type="text/javascript">
function
GetLocalTimeOffset()
{
var rightNow =
new Date();
var date1 =
new
Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
var temp =
date1.toGMTString();
var date2 =
new Date(temp.substring(0,
temp.lastIndexOf(" ")-1));
var hoursDiffStdTime =
(date1 - date2) / (1000 * 60 * 60);
createCookie( "hoursDiffStdTime", hoursDiffStdTime, 0);
}
function
createCookie(name,value,days) {
if (days &&
days > 0) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires =
"; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+ "="+value+expires+"; path=/";
}
</script>
</ head>
< body onload="GetLocalTimeOffset();">
...
default.aspx:
Here is how
we getting time difference on the server from the client, attaching it to
the profile and passing it to calculate display values
Profile.hoursDiffStdTime = Double.Parse(Request.Cookies["hoursDiffStdTime"].Value );
Label1.Text = TimeZoneManager.DisplayDateTime(DateTime.Now, Profile);
timezonemanager.cs:
Xml doc which holds time zones is
located in app_data and looks like this:
<? xml
version="1.0" encoding="utf-8" ?>
< root>
< option value="-12.00"
>Eniwetok, Kwajalein</option>
< option value="-11.00"
>Midway Island, Samoa</option>
< option value="-10.00"
>Hawaii</option>
< option value="-9.00" >Alaska</option>
< option value="-8.00" >Pacific Time
(US &
Canada)</option>
< option value="-7.00" >Mountain Time
(US &
Canada)</option>
< option value="-6.00" >Central Time
(US & Canada),
Mexico City</option>
< option value="-5.00" >Eastern Time
(US & Canada),
Bogota, Lima, Quito</option>
< option value="-4.00" >Atlantic Time
(Canada), Caracas, La Paz</option>
< option value="-3.50" >Newfoundland</option>
< option value="-3.00" >Brazil,
Buenos Aires, Georgetown</option>
< option value="-2.00" >Mid-Atlantic</option>
< option value="-1.00" >Azores, Cape
Verde Islands</option>
< option value="0.00" >Western
Europe Time, London, Lisbon, Casablanca, Monrovia</option>
< option value="1.00" >CET(Central
Europe Time), Brussels, Copenhagen, Madrid, Paris</option>
< option value="2.00" >EET(Eastern
Europe Time), Kaliningrad, South Africa</option>
< option value="3.00" >Baghdad,
Kuwait, Riyadh, Moscow, St. Petersburg, Volgograd, Nairobi</option>
< option value="3.50" >Tehran</option>
< option value="4.00" >Abu Dhabi,
Muscat, Baku, Tbilisi</option>
< option value="4.50" >Kabul</option>
< option value="5.00" >Ekaterinburg,
Islamabad, Karachi, Tashkent</option>
< option value="5.50" >Bombay,
Calcutta, Madras, New Delhi</option>
< option value="6.00" >Almaty,
Dhaka, Colombo</option>
< option value="7.00" >Bangkok,
Hanoi, Jakarta</option>
< option value="8.00" >Beijing,
Perth, Singapore, Hong Kong, Chongqing, Urumqi, Taipei</option>
< option value="9.00" >Tokyo, Seoul,
Osaka, Sapporo, Yakutsk</option>
< option value="9.50" >Adelaide,
Darwin</option>
< option value="10.00" >EAST(East
Australian Standard), Guam, Papua New Guinea, Vladivostok</option>
< option value="11.00" >Magadan,
Solomon Islands, New Caledonia</option>
< option value="12.00" >Auckland,
Wellington, Fiji, Kamchatka, Marshall Island</option>
< option value="13.00" >Nuku"alofa</option>
</ root>
We are using XPathDocument
class here. XPathDocument works fasrer than XmlDocument
so we are using it to get time zone name based on the time difference.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Runtime.Remoting.Messaging;
using System.Xml.XPath;
using System.Xml;
/// <summary>
/// Summary description for
TimeZoneManager
/// </summary>
public class TimeZoneManager
{
///
<summary>
/// Gets
the time zone.
///
</summary>
///
<param name="offset">The offset.</param>
///
<returns></returns>
private static string GetTimeZone(double offset)
{
//Adjust result based on the server time
zone
string timeZoneKey =
"timeOffset" +
offset.ToString("F");
string result =
(CallContext.GetData(timeZoneKey) ?? "").ToString();
if (result.Length ==
0)
{
string zonesDocPath =
HttpRuntime.AppDomainAppPath +"app_data/TimeZones.xml";
XPathDocument
timeZonesDoc = new
XPathDocument(zonesDocPath);
try
{
string xPath =
"/root/option[@value='" +
offset.ToString("F") +
"']";
XPathNavigator
searchNavigator = timeZonesDoc.CreateNavigator();
XmlNamespaceManager
nsmgr = new XmlNamespaceManager(searchNavigator.NameTable);
XPathNodeIterator
iterator = searchNavigator.Select(xPath, nsmgr);
if
(iterator.MoveNext())
{
result = iterator.Current.Value;
if (!string.IsNullOrEmpty(result))
{
CallContext.SetData(timeZoneKey, result);
}
}
}
catch (Exception ex)
{
return ex.Message;
}
}
return result;
}
///
<summary>
///
Displays the date time.
///
</summary>
///
<param name="dateTime">The date time.</param>
///
<param name="profile">The profile.</param>
///
<returns></returns>
public static string DisplayDateTime(DateTime dateTime, ProfileCommon profile)
{
//Move to universal time (GMT) with Zero
offset
DateTime utcDateTime =
dateTime.ToUniversalTime();
//Add client side offset
DateTime resultDateTime
= utcDateTime.AddHours(profile.hoursDiffStdTime + 1);
return string.Concat(resultDateTime.ToShortDateString(), ", ", resultDateTime.ToShortTimeString(),
", ",
GetTimeZone(profile.hoursDiffStdTime));
}
}
| You must Sign In to use this message board. |
|
| | Msgs 1 to 15 of 15 (Total in Forum: 15) (Refresh) | FirstPrevNext |
|
 |
|
|
This is exactly what I needed for for an app I'm working on. I wanted to get the users' time zones without burdening them with difficult questions like "What time zone are you in?". Great Post. Bookmarked it.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
I am in the US (during daylight savings time. ) I downloaded the project and ran it. It worked fine. It shows that I am in central Time. Then I noticed the posts and made the changes. Afterwards the page showed that I was in eastern time, which is wrong. I do know that my pc automatically handles daylight savings time (the Windows check box in the date and time settings...) I don't know if that matters. Are the script changes in the post valid?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I had the same issue. Perhaps it was due to integer rounding somewhere? I gave a solution in this post: http://www.codeproject.com/useritems/Remote_Time_Zone.asp?msg=2340027#xx2340027xx
Kirby Zhang
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, I think there is a problem with the daylight saving time.
The line:
DateTime resultDateTime = utcDateTime.AddHours(profile.hoursDiffStdTime + 1);
always sum "1" to the time offset, but this is correct only when Daylight saving time is active (summer). The correct solution is to calculate the correct time offset on the client, where your code fails because you do not care about the day of the year. This shoud be ok:
var rightNow = new Date(); var date1 = new Date(rightNow.getFullYear(), rightNow.getMonth(), rightNow.getDay(), 0, 0, 0, 0); var temp = date1.toGMTString(); var date2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); var hoursDiffStdTime = (date1 - date2) / (1000 * 60 * 60); ..
With this the hoursDiffStdTime is the correct time offset, because date1 is calculated with the correct day of the year. So, the "+1" is not more needed:
DateTime resultDateTime = utcDateTime.AddHours(profile.hoursDiffStdTime);
chrjs
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Christian, Thanks you so much, this is very good point. The code was not correctly handled daylight savings. But the way you proposing to change the code is not working for me. The correct fix would be to add bool property to the profile indicatiing if user in daylite saving time zone. So here are the changes:
1)web.config:
2) The best javascript solution for the daylight saving i found here: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CFB006C45F7[^] So based on that javascript changed to this: function GetLocalTimeOffset() { var rightNow = new Date(); var date1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0); var date2 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0); var temp = date1.toGMTString(); var date3 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); var temp = date2.toGMTString(); var date4 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); var hoursDiffStdTime = (date1 - date3) / (1000 * 60 * 60); var hoursDiffDaylightTime = (date2 - date4) / (1000 * 60 * 60); if (hoursDiffDaylightTime == hoursDiffStdTime) { //Daylight Saving Time is NOT observed here. createCookie("daylightSavingTime", "false", 0); } else { //Daylight Saving Time is observed here. createCookie("daylightSavingTime", "true", 0); } createCookie("hoursDiffStdTime", hoursDiffStdTime, 0); //alert(readCookie("hoursDiffStdTime")); }
3)To set daylight savings on the server we will add this line: Profile.daylightSavingTime= bool.Parse(Request.Cookies["daylightSavingTime"].Value );
4)Manager class: instead of: DateTime resultDateTime = utcDateTime.AddHours(profile.hoursDiffStdTime + 1); there will be: resultDateTime = utcDateTime.AddHours(profile.hoursDiffStdTime + (profile.daylightSavingTime?1 ));
Please let me know if anyone want me to repost updated code.
Thanks, Dmitry
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Dmitry,
it is strange that my code does not work for you (i'm talking about the client side code). Maybe we do not want the same think from client. Look at this sample html page:
<html> <head> <script language="javascript"> function showTimezone() { var rightNow = new Date(); var date1 = new Date(rightNow.getFullYear(), rightNow.getMonth(), rightNow.getDay(), 0, 0, 0, 0); var temp = date1.toGMTString(); var date2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); var hoursDiffStdTime = (date1 - date2) / (1000 * 60 * 60); alert(hoursDiffStdTime); } </script> </head> <body önload="showTimezone()"> </body> </html>
The code make the difference, in hours, from the current client time to the current GMT time. This is all you need to convert on the server from globaltime to client local time, obviously if you start from a GMT time.
On my machine i'm in +1 time zone (Italy), now we are in daytlight saving time, so this page print "2", that is the correct offset from GMT. Later, in november for example, there isn't daylight saving time, and my page correctly print "1" as time offset.
On server side, this number is all that you need: clientTime = globalGMTTime.AddHours(cookievalue); Let me know if I misunderstand something!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
Using Christian's code it was one hour too fast here in Pacific Time, daylight savings off. It had this problem on two browsers. Perhaps there was integer truncation somewhere?
This is the version I'm using which works for me.
var rightNow = new Date(); var temp = rightNow.toGMTString(); var gmtNow = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); // the x= round(x*2)/2 is used for rounding time zone with half hour offsets var hoursDiffStdTime = Math.round((rightNow - gmtNow) / (1000 * 60 * 60) * 2) / 2;
I'm using your code for a scheduling gadget on my front page: http://www.battleballgame.net
Kirby Zhang
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Thanks. That is interesting and very useful article. But this article shows the way to use DateTime Values according to the remote time zone in your ASP.NET applications, while that article is very generic (but still usefull)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have found the DST code very useful and used it for a world clock cisco Xml IP phone service for my company. (Xslt, C# & ASP.NET)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|