Tech Off Thread

26 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Time Zone Problems -- stacy and mike can you help?

Back to Forum: Tech Off
  • User profile image
    figuerres

    I have looked at the code in two code project articles and seem to be kinda stuck.

    they both seem to have the same problem.


    in transalting a datetime from GMT to local they give the wrong answer each time!

    for example GMT 10:50pm today comes back as -5 or 5:50pm Eastern time.

    the right answer should be -4 or 6:50pm

    seems like the windows api call is in error, looks like the tzi is loaded with the right values in the .net code.

    not sure if this is a windows bug from the 2007 patch or ???

  • User profile image
    figuerres

    figuerres wrote:
    I have looked at the code in two code project articles and seem to be kinda stuck.

    they both seem to have the same problem.


    in transalting a datetime from GMT to local they give the wrong answer each time!

    for example GMT 10:50pm today comes back as -5 or 5:50pm Eastern time.

    the right answer should be -4 or 6:50pm

    seems like the windows api call is in error, looks like the tzi is loaded with the right values in the .net code.

    not sure if this is a windows bug from the 2007 patch or ???



    Update:  actually it looks like the source time conversion is wrong!

    I have an app that the user needs to input an event date/time in a selected time zone. then I need to store the local time for the server to use.

    sample:   from Mid-Atlantic time of 8:50pm to FL time
    looks like the GMT time stage is in error.
    Mid-Atlantic should be -1 right now but the local to gmt is maiking it -2

    so then the GMT to FL time is an hour off.

    yes Mid-Atlantic the app is used on board a ship at sea.
    and they want local time -- I'm tempted to tell them to use GMT but the end users are passengers on the ship who often will be confused about the shifting time zones as they sail.

    PS: the input is done via web pages, the server is in FL the ship is at sea.... so I need to create a datetime for the target location and then work back to what that is in FL.

  • User profile image
    Matthew van Eerde

    There's an Eastern (Indiana) which does not observe DST.

    EDIT: never mind, looks like it was something else.

    > the app is used on board a ship at sea.

    That is so cool.

  • User profile image
    figuerres

    Matthew van Eerde wrote:
    There's an Eastern (Indiana) which does not observe DST.

    EDIT: never mind, looks like it was something else.

    > the app is used on board a ship at sea.

    That is so cool.


    Hey if you would please ask around... it's the win32 api calls that seem to not be working...

    mike dimmik (sp) and Stacy have each shared some code on code project that is supposed to do timezone conversion via the windows api calls, also a web site sells a date and time package that seems to be the same stuff and seems to have the same problem.

    as far as I can tell the code is calling the win32 functions and they are not doing the right thing...

    if all else fails I may have to duplicate the windows function and read the time zone info and do the offsets but I am not 100% sure of how to use that data in all cases.  some timezones seem to determine the switch differently and I want to get it right.

  • User profile image
    JohnAskew

    I'm not sure if this will help since it doesn't address the 'switch' issue you pointed out, but I've gone the route of holding a TimeSpan value for the current time and applied Time Zone offsets to it to create a DateTime value when needed.

    XML Serialization doesn't handle TimeSpan correctly, I should add.

    Here is some code from when I was using DateTime values and correcting for the machine's locale

    // input:
    // <XMLSerializedDateTime>
    //  2006-12-10T12:00:00-08:00
    // </XMLSerializedDateTime>
    private DateTime TimeZoneCorrectedDateTime(string xmlDateTime)
    {
       DateTime result = DateTime.MinValue;
       if (xmlDateTime != String.Empty)
       {
          if (DateTime.TryParse(xmlDateTime, out result))
          {
             string strTimeZoneOffset = 
                xmlDateTime.Substring(xmlDateTime.LastIndexOf(':') - 3);

             int hours = Int32.Parse(strTimeZoneOffset.Substring(1, 
                strTimeZoneOffset.IndexOf(':') - 1));

             int mins = Int32.Parse(strTimeZoneOffset.Substring
                (strTimeZoneOffset.IndexOf(':') + 1));

             if (strTimeZoneOffset[0] == '-')
                mins += (hours *= -60);
             else
                mins += (hours * 60);

             TimeSpan storedOffset = TimeSpan.FromMinutes(mins);
             TimeSpan localOffset = 
                TimeZone.CurrentTimeZone.GetUtcOffset(
                   new DateTime(result.Year, result.Month, result.Day));

             result = 
                result.AddMinutes(storedOffset.TotalMinutes - 
                   localOffset.TotalMinutes);
          }
       }   
       return result;
    }

    Here's code after deciding to use TimeSpans instead.

    This allows me to have time-of-day independent of time zones.

    My data carries the DateTime of the date (midnight) so I can construct a DateTime when I need by adding TimeSpan.TotalMinutes to that date (midnight).

    NOTE: You have to work around an XmlSerializer bug to use TimeSpan variables.

    Here's an example of this work around to store TimeSpan in XML:

    [XmlElement("Call", DataType = "duration")] 
    public string CallXml
    {
       get
       {
         if (this.Call < TimeSpan.FromSeconds(1))
             return String.Empty;
          else
             return XmlConvert.ToString(this._call);
       }

       set
       {
          if (value == String.Empty)
          {
             this._call = TimeSpan.Zero;
             return;
         }

          TimeSpan newInterval = XmlConvert.ToTimeSpan(value);
          if (this._call == newInterval)
             return;
          this._call = newInterval;
       }
    }

    [XmlIgnore]
    public TimeSpan Call
    {
       get { return this._call; }
       set { this._call = value; }
    }


  • User profile image
    Cannot​Resolve​Symbol

    figuerres wrote:
     Update:  actually it looks like the source time conversion is wrong!

    I have an app that the user needs to input an event date/time in a selected time zone. then I need to store the local time for the server to use.

    sample:   from Mid-Atlantic time of 8:50pm to FL time
    looks like the GMT time stage is in error.
    Mid-Atlantic should be -1 right now but the local to gmt is maiking it -2

    so then the GMT to FL time is an hour off.

    yes Mid-Atlantic the app is used on board a ship at sea.
    and they want local time -- I'm tempted to tell them to use GMT but the end users are passengers on the ship who often will be confused about the shifting time zones as they sail.

    PS: the input is done via web pages, the server is in FL the ship is at sea.... so I need to create a datetime for the target location and then work back to what that is in FL.


    It looks to me like the Windows GMT (Dublin, Edinburgh, Lisbon, London) time zone adjusts for daylight savings time...  so you're going to get those results.  The other GMT zone (Casablanca, Monrovia, Reykjavik) should produce the correct behavior, because it doesn't appear to adjust for DST.  That is, if you can access it through Win32...  (not familiar with the time zone API).

  • User profile image
    figuerres

    JohnAskew wrote:
    I'm not sure if this will help since it doesn't address the 'switch' issue you pointed out, but I've gone the route of holding a TimeSpan value for the current time and applied Time Zone offsets to it to create a DateTime value when needed.

    XML Serialization doesn't handle TimeSpan correctly, I should add.

    Here is some code from when I was using DateTime values and correcting for the machine's locale

    // input:
    // <XMLSerializedDateTime>
    //  2006-12-10T12:00:00-08:00
    // </XMLSerializedDateTime>
    private DateTime TimeZoneCorrectedDateTime(string xmlDateTime)
    {
       DateTime result = DateTime.MinValue;
       if (xmlDateTime != String.Empty)
       {
          if (DateTime.TryParse(xmlDateTime, out result))
          {
             string strTimeZoneOffset = 
                xmlDateTime.Substring(xmlDateTime.LastIndexOf(':') - 3);

             int hours = Int32.Parse(strTimeZoneOffset.Substring(1, 
                strTimeZoneOffset.IndexOf(':') - 1));

             int mins = Int32.Parse(strTimeZoneOffset.Substring
                (strTimeZoneOffset.IndexOf(':') + 1));

             if (strTimeZoneOffset[0] == '-')
                mins += (hours *= -60);
             else
                mins += (hours * 60);

             TimeSpan storedOffset = TimeSpan.FromMinutes(mins);
             TimeSpan localOffset = 
                TimeZone.CurrentTimeZone.GetUtcOffset(
                   new DateTime(result.Year, result.Month, result.Day));

             result = 
                result.AddMinutes(storedOffset.TotalMinutes - 
                   localOffset.TotalMinutes);
          }
       }   
       return result;
    }

    Here's code after deciding to use TimeSpans instead.

    This allows me to have time-of-day independent of time zones.

    My data carries the DateTime of the date (midnight) so I can construct a DateTime when I need by adding TimeSpan.TotalMinutes to that date (midnight).

    NOTE: You have to work around an XmlSerializer bug to use TimeSpan variables.

    Here's an example of this work around to store TimeSpan in XML:

    [XmlElement("Call", DataType = "duration")] 
    public string CallXml
    {
       get
       {
         if (this.Call < TimeSpan.FromSeconds(1))
             return String.Empty;
          else
             return XmlConvert.ToString(this._call);
       }

       set
       {
          if (value == String.Empty)
          {
             this._call = TimeSpan.Zero;
             return;
         }

          TimeSpan newInterval = XmlConvert.ToTimeSpan(value);
          if (this._call == newInterval)
             return;
          this._call = newInterval;
       }
    }

    [XmlIgnore]
    public TimeSpan Call
    {
       get { return this._call; }
       set { this._call = value; }
    }






    Hmmm....

    well the problem is that I need to know the right offset to use.

    see the windows api is supposed to find the timezone offset and do the math for me.
    with all the different possible time zones and that some places use different rules on when and how or even if they will change from std to daylight ....

    if I knew for sure what offsets to use then I would use timespans in c# that's the nasty part....



  • User profile image
    figuerres

    CannotResolveSymbol wrote:
    

    figuerres wrote:  Update:  actually it looks like the source time conversion is wrong!

    I have an app that the user needs to input an event date/time in a selected time zone. then I need to store the local time for the server to use.

    sample:   from Mid-Atlantic time of 8:50pm to FL time
    looks like the GMT time stage is in error.
    Mid-Atlantic should be -1 right now but the local to gmt is maiking it -2

    so then the GMT to FL time is an hour off.

    yes Mid-Atlantic the app is used on board a ship at sea.
    and they want local time -- I'm tempted to tell them to use GMT but the end users are passengers on the ship who often will be confused about the shifting time zones as they sail.

    PS: the input is done via web pages, the server is in FL the ship is at sea.... so I need to create a datetime for the target location and then work back to what that is in FL.


    It looks to me like the Windows GMT (Dublin, Edinburgh, Lisbon, London) time zone adjusts for daylight savings time...  so you're going to get those results.  The other GMT zone (Casablanca, Monrovia, Reykjavik) should produce the correct behavior, because it doesn't appear to adjust for DST.  That is, if you can access it through Win32...  (not familiar with the time zone API).



    this call:
    http://msdn2.microsoft.com/en-us/library/ms724949.aspx

    BOOL SystemTimeToTzSpecificLocalTime(
      LPTIME_ZONE_INFORMATION lpTimeZone,
      LPSYSTEMTIME lpUniversalTime,
      LPSYSTEMTIME lpLocalTime
    );
    

    is the thing that seems to be bugged.


    or my understanding of it is wrong.


    my reading seems to say that correclty go from time zone a to b you should go from a to UTC and then from UTC to b

    this is to allow for local timezones having different rules about std/dst and the like.

    http://msdn2.microsoft.com/en-us/library/ms973825.aspx



    what do you get for mid-atlantic to GMT/UTC??

    I have to create a user specified datetime and timezone and then convert it to local florida time for the server in fl.

    that win32 call is supposed to know the right offset to use.

    you call it twice
    one time to take say mid-atlantic to GMT
    then to take GMT to eastern time.

    hmmm just found this to read also:
    http://blogs.msdn.com/kathykam/archive/2006/07/13/665019.aspx


  • User profile image
    JohnAskew

    What I like about XMLSerialization of DateTime types is that the offset is readable.

    // <XMLSerializedDateTime>
    //  2006-12-10T12:00:00-08:00
    // </XMLSerializedDateTime>

    The user's machine has the TimeZone information, so that is what I use to find the offset; they send XMLSerialized DateTime.

    CRS wrote:
    I have to create a user specified datetime and timezone and then convert it to local florida time for the server in fl.


    You can parse out the offset from XML and apply the offset for Florida, instead of having the Florida server determine the TimeZone in which the user originated the message. DST is already handled in the calculation of the DateTime on the users' machine; and the total offset is given to you regardless of their TimeZone.

    Perhaps I don't understand. Do you have to generate this data in Florida for both the user and the server?

  • User profile image
    figuerres

    JohnAskew wrote:
    

    What I like about XMLSerialization of DateTime types is that the offset is readable.

    // <XMLSerializedDateTime>
    //  2006-12-10T12:00:00-08:00
    // </XMLSerializedDateTime>

    The user's machine has the TimeZone information, so that is what I use to find the offset; they send XMLSerialized DateTime.

    CRS wrote: I have to create a user specified datetime and timezone and then convert it to local florida time for the server in fl.


    You can parse out the offset from XML and apply the offset for Florida, instead of having the Florida server determine the TimeZone in which the user originated the message. DST is already handled in the calculation of the DateTime on the users' machine; and the total offset is given to you regardless of their TimeZone.

    Perhaps I don't understand. Do you have to generate this data in Florida for both the user and the server?



    the server is in fl, on local time.

    the user is on a ship at sea, they are using a web browser to input a date and time for a future event.

    so the users date and time are not used and can not be used --
    they may have for example just left the dock and need to set a date and time for an even that may not happen till the ship is in say the med. or off the coast of africa etc....

    so what they want to see is the target date and time of the future event.

    but all the code in the server is written to use a single timezone. server time.

    so what I am trying to do is use the input to create two datetime values, one to show the user, the other to manage the data on the server, both should represent the same "Moment in time"
    so that for example if this was a phone conf between two parties one in fl and the other on the ship they would both know when to call or expect a call to come in.

    does that clear it up a bit ??

  • User profile image
    JohnAskew

    If, somehow, you knew their location, you could calculate from the server time to correct for their current TimeZone.

    GPS coordinates?

    Perhaps the user can select a 'Time Zone' and the DateTime can be calculated on the client-side; while the server time remains EST?

     

  • User profile image
    figuerres

    JohnAskew wrote:
    

    If, somehow, you knew their location, you could calculate from the server time to correct for their current TimeZone.

    GPS coordinates?

    Perhaps the user can select a 'Time Zone' and the DateTime can be calculated on the client-side; while the server time remains EST?

     



    Let's try this again....

    they are in say GMT -3 time zone.

    they are entering a *FUTURE DATE AND TIME* for a timezone they are not in right now.

    Say for GMT -1

    so the client's date and time are 100% totaly not usefull at all.

    this is on a ship that is traveling, they are planning events in the future.

    they do select a zone and a datetime .... but it's not for the clients local time zone and it's not for the servers local time zone.

    thus the need to call a windows api that is uspposed to know how to do the right math.

    or I have to not use windows and use some kind of 3rd party solution.
    ( for the timezone database )


  • User profile image
    JohnAskew

    Link for VS and the new DST rules... not that it applies here exactly.


    Perhaps you can collect both the Zone and DateTime on the FL server as distinct fields. This is if you're client-side is doing the math for the conversion; let the server handle it instead?

    The C# TimeZone and DateTime types rely on the Win32 and system time, so no help there.

    ms wrote:
    Time and time zone-aware features of the .NET Framework, such as the System.TimeZone class, will automatically reflect these rule changes provided updates are applied to the operating system.



    Does the server in FL need the DST patch? I'm sure you've looked at that, and DST now is (new & old) -in effect...


    If the server knows the location and the (local) time for that location of a scheduled event, then you can provide an adapter of your own to correct on the server. How is the call giving bad results? You are one hour off and I would suspect the DST stuff.
    Perplexed

  • User profile image
    Matthew van Eerde

    The new DST law is not in play currently... the old law is the same as the new except for a few weeks in March and a week in October.

    But DST could still be the culprit.

    Which particular EST time zone is the server in?  Which particular GMT are you using?

    The EST time zone should be one that does observe DST, the GMT should be one that does not.

  • User profile image
    RichardRudek

    figuerres wrote:
    
    Let's try this again....

    they are in say GMT -3 time zone.

    they are entering a *FUTURE DATE AND TIME* for a timezone they are not in right now.

    Say for GMT -1

    so the client's date and time are 100% totaly not usefull at all.

    this is on a ship that is traveling, they are planning events in the future.

    they do select a zone and a datetime .... but it's not for the clients local time zone and it's not for the servers local time zone.


    [snip]

    So, your saying that the user states that they want, for example, to be  woken up each morning, at 7am local time. Which means that as they travel, their local time is changing along with their position on the globe, right ?

    If so, I don't see what the problem is. When I use the Win32 GetSystemTime() call, I get a UTC time. There's no call needed to convert from the Server's local time into UTC - it's already UTC.

    However, I do a see that their could be a problem in being able to accurately determine which timezone the ship will be in, at a future date.

    EDIT:

    It's 10:30 AM, here in Australia (GMT +10):




    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) 
    {
    SYSTEMTIME st;
    GetSystemTime(&st);
    label1->Text = String::Format("Day {0}, {1:00}-{2:00}-{3:0000}, {4:00}:{5:00}:{6:00}.{7:000}",
    st.wDayOfWeek, st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    }

  • User profile image
    figuerres

    Matthew van Eerde wrote:
    The new DST law is not in play currently... the old law is the same as the new except for a few weeks in March and a week in October.

    But DST could still be the culprit.

    Which particular EST time zone is the server in?  Which particular GMT are you using?

    The EST time zone should be one that does observe DST, the GMT should be one that does not.



    this code:

    public static DateTime ToLocalTime(string sourceTimeZoneName, DateTime localTime, string targetTimeZoneName)

    {

    DateTime utc = TimeZoneInformation.ToUniversalTime(sourceTimeZoneName, localTime);

    DateTime lt = TimeZoneInformation.ToLocalTime(targetTimeZoneName, utc);

    return lt;

    }

    calls this code:

    public static DateTime ToUniversalTime(string standardTimeZoneName, DateTime local)

    {

    TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(standardTimeZoneName);

    return tzi.ToUniversalTime(local);

    }

    public static DateTime ToLocalTime(string standardTimeZoneName, DateTime utc)

    {

    TimeZoneInformation tzi = TimeZoneInformation.GetTimeZone(standardTimeZoneName);

    return tzi.ToLocalTime(utc);

    }


    public DateTime ToLocalTime(DateTime utc)

    {

    // Convert to SYSTEMTIME

    SYSTEMTIME stUTC = DateTimeToSystemTime(utc);

    // Set up the TIME_ZONE_INFORMATION

    TIME_ZONE_INFORMATION tziNative = TziNative();

    SYSTEMTIME stLocal;

    NativeMethods.SystemTimeToTzSpecificLocalTime(ref tziNative, ref stUTC, out stLocal);

    // Convert back to DateTime

    return SystemTimeToDateTime(ref stLocal);

    }



    my original post refered to:

    /// <summary>

    /// Date: 12/4/2005

    /// Created By: William Stacey [MVP]

    /// Credit: Thanks to Mike Dimmick for his work at http://www.codeproject.com/dotnet/WorldClock.asp,

    /// Time zone conversion helper class. Used to convert to/from utc times and local times and respect DST.

    /// Can also covert between two local time zones.

    /// Information about a time zone containing methods to convert local times to and from UTC and

    /// between local time zones.

    /// </summary>

    they both are 9er's  but so far have not commented and I guess not seen this post/thread

    and I have not had time to lookup an email addr for them....

    I am working on several projects so I find I make silly jokes about time .... I don't have time to fix the time cause I am running out of time  :--)

    I hope that before this week is over I can spend some time on this problem and get to the root of it!

  • User profile image
    figuerres

    RichardRudek wrote:
    

    [snip]

    So, your saying that the user states that they want, for example, to be  woken up each morning, at 7am local time. Which means that as they travel, their local time is changing along with their position on the globe, right ?

    If so, I don't see what the problem is. When I use the Win32 GetSystemTime() call, I get a UTC time. There's no call needed to convert from the Server's local time into UTC - it's already UTC.

    However, I do a see that their could be a problem in being able to accurately determine which timezone the ship will be in, at a future date.



    that last bit is amost exactly right, I know what the server time is just fine.

    but the user is entering a date and time for a location that they are *NOT IN*

    they do know where the ship will be -- it's a big comerical cruze ship, they have a planned trip and have to meet that plan.

    but they need my app to "do the math" for them.

    right now they are entering the numbers manually cause they told me my attempt at auto-computing the values was in error by a one hour factor.

    so now I am trying to nail down where the error comes from. and how to fix it.

    I have done some tests and it seems that the first leg from the "future date-time in x"  to "future date-time in UTC" is one hour off which then casues the step of going from UTC to FL time to be off by the same amount.

    this is a real PITA to sort out cause not all zones work the same and there are timezone web sites that do show me world time but not using the same names as the windows list of zone names.....
    so I have to find some that I can be sure are the same as windows to test with.....

    or I may have to see If I can use a UNIX ZoneInfo db that is portable
    or something like that...


  • User profile image
    RichardRudek

    figuerres wrote:
    
    that last bit is amost exactly right, I know what the server time is just fine.

    but the user is entering a date and time for a location that they are *NOT IN*

    they do know where the ship will be -- it's a big comerical cruze ship, they have a planned trip and have to meet that plan.

    but they need my app to "do the math" for them.

    right now they are entering the numbers manually cause they told me my attempt at auto-computing the values was in error by a one hour factor.

    so now I am trying to nail down where the error comes from. and how to fix it.

    I have done some tests and it seems that the first leg from the "future date-time in x"  to "future date-time in UTC" is one hour off which then casues the step of going from UTC to FL time to be off by the same amount.


    [snip]

    OK. I think I get it, now.

    But I'm noticing that you seem to be flip-flopping between .NET (CLR) methods and Win32. Sticking to Win32, have you tried using TzSpecificLocalTimeToSystemTime()  first, which will give you the (future) UTC from the user-entered (future) local-time and TZ, then use SystemTimeToTzSpecificLocalTime() to convert it to your Server's local time ?.

    If so, then I'll spend a few more minutes on it, tomorrow morning, and see if I run into the same problem (using C++).

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.