Let’s say you have a customer base spreaded across several time zones i.e. from Hawaii to Alaska, all the way across mainland US and even some remote parts of Europe. You want a service to deliver a particular message at certain time via email, in that time zone. How would you do that?
This problem recently came up and was discussed with some colleagues. I found it to be pretty challenging; even though it sounds simple, it gets a bit tricky if you’d want to find out things like
- At what time in your local timezone the message should be sent out so it will reach the target timezone at the given local time (at target timezone say 8:00 AM)
- Relative to your current timezone, when did the target time for message delivery occurred in the destination timezone locale?
etc etc.
Therefore, I started experimenting with the following data
|
96811 P Honolulu D Honolulu 15003 HI 15 3320 808 Hawaii -10 |
|
99850 P Juneau D Juneau 02110 AK 02 0000 907 Alaska -9 |
|
97840 S Oxbow D Baker 41001 OR 41 0000 541 Pacific -8 |
|
59821 S Arlee D Lake 30047 MT 30 0000 406 Mountain -7 |
|
78028 S Kerrville DKerr 48265 TX 48 0000 830 Central -6 |
|
48852 P McBrides D Montcalm 26117 MI 26 0000 989 Eastern -5 |
|
00627 S VISTA Verde NCamuy 72027 PR 72 0470 787 Atlantic -4 |
A simple no brainer equation for time calculation in a particular locale is
LocalTime = GMT + Offset
where offset is the value by which a local time differs from UTC or coordinated universal time.
Hence, it can be said that
PacificTime = GMT + (-8)
HawaiianTime = GMT + (-10)
Equating both equations we get
PacificTime + 8 = HawaiianTime + 10
And hence
PacificTime = HawaiinTime + 10 – 8
Considering Pacific time as local timezone and Hawaiian timezone as the target one, this can be generalized as
LocalTimeZone = TargetTimeZone + TargetGMTOffset – LocalGMTOffset
I did a C# implemention of this idea which, AFAIK, provides pretty accurate results. Like for the following PR zip 00627.
Local Time is 12/31/2005 12:46:31 AM Which is UTC-8
Universal Time (GMT) is 12/31/2005 8:46:31 AM
Target time is 12/31/2005 8:00:00 AM
Time in zipcode 00627 is 12/31/2005 4:46:31 AM which is UTC-4
Required Time 12/31/2005 8:00:00 AM in zipcode 00627 is in 3.00 Hrs 13.00 Mins.
Time difference between Local and Remote Zone is -4
According to local time, alert has to occur at 12/31/2005 4:00:00 AM to be seenin target locale at 12/31/2005 8:00:00 AM
And hence comes the following code:
class TimeZoneCalibrator
{
public static string[] strzipcode = {"96811", "99850", "97840", "59821", "78028", "48852", "00627", "IG119XW"};
public static int[] offset = {-10, -9, -8, -7, -6, -5, -4, 0};
/// <summary>
/// The driver - traverse through different time zones including GMT
/// </summary>
[STAThread]
static void Main(string[] args)
{
DateTime RequiredRemoteTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 8, 0, 0, 0);
for (int cnt=0; cnt<strzipcode.Length; cnt++)
CalibrateTime (RequiredRemoteTime, strzipcode[cnt]);
Console.ReadLine ();
}
//Returns the local time in that time zone
public static DateTime CalibrateTime (DateTime RequiredRemoteTime, string zipcode)
{
int strIndex=0;
int strNumber = 0;
for (strNumber = 0; strNumber < strzipcode.Length; strNumber++)
{
strIndex = strzipcode[strNumber].IndexOf(zipcode);
if (strIndex >= 0)
break;
}
DateTime localDateTime = DateTime.Now;
System.DateTime univDateTime = localDateTime.ToUniversalTime();
double GMTDifferenceTimeSpan = localDateTime.Subtract(univDateTime).TotalHours;
//Find out the remote time
DateTime RemoteDateTime = univDateTime.AddHours (offset[strNumber]);
TimeSpan TimeDifference = RequiredRemoteTime.Subtract (RemoteDateTime);
//Localtime relative
DateTime LocalTimeAnticipated = RequiredRemoteTime;
int LocalRemoteTimeDiff = (int)(TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).TotalHours - offset[strNumber]);
LocalTimeAnticipated = LocalTimeAnticipated.AddHours (LocalRemoteTimeDiff);
Console.WriteLine ("Local Time is " + localDateTime.ToString () + " Which is UTC" + TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).TotalHours);
Console.WriteLine ("Universal Time (GMT) is " + univDateTime.ToString ());
Console.WriteLine ("Target time is " + RequiredRemoteTime.ToString ());
Console.WriteLine ("Time in zipcode " + zipcode + " is " + RemoteDateTime.ToString ()+ " which is UTC" + offset[strNumber]);
//Just for fancy printing.
if (TimeDifference.TotalHours < 0)
Console.WriteLine ("Required Time " + RequiredRemoteTime + " in zipcode " + zipcode + " was "
+ Math.Abs (TimeDifference.Hours).ToString ("N") +" Hrs " + Math.Abs (TimeDifference.Minutes).ToString ("N")+" Mins ago.");
else
Console.WriteLine ("Required Time " + RequiredRemoteTime + " in zipcode " + zipcode + " is in "
+ Math.Abs (TimeDifference.Hours).ToString ("N") +" Hrs " + Math.Abs (TimeDifference.Minutes).ToString ("N") +" Mins.");
Console.WriteLine ("Time difference between Local and Remote Zone is " + LocalRemoteTimeDiff);
//According to local time, it would occur at
Console.WriteLine ("According to local time, alert has to occur at " + LocalTimeAnticipated.ToString () +" to be seen in target locale at " + RequiredRemoteTime.ToString ());
Console.WriteLine ("--------------------------------------------------------------");
return LocalTimeAnticipated;
}
DateTime Structure