Announcement

Collapse
No announcement yet.

Daylight Savings Time

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Daylight Savings Time

    If I know UTC time and the time difference between my location and UTC time, I still have to account for daylight savings time hour difference to know the local time.

    How do world clock builders know if a locale is on/off daylight savings time?


  • #2
    Take a look at https://forum.powerbasic.com/forum/u...rld#post815573

    The key function for your purpose is:

    Code:
    FUNCTION GetCurrentTimeinZone (TZName AS WSTRING) AS WSTRING
         LOCAL PT AS IPOWERTIME
         pt = CLASS "PowerTime"
         LOCAL TZI AS TIME_ZONE_INFORMATION
         LOCAL RegTZI AS REG_TZI_FORMAT
         LOCAL hKey AS DWORD
         LOCAL lngRetVal,lngSize AS LONG
         LOCAL st1, st2 AS systemtime
         lngSize = SIZEOF(RegTZI)
    
        'Get TZI info from Registry -
        lngRetVal = RegOpenKeyEx(%HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" & TZName,0,%key_query_value,hkey)
        IF lngRetVal THEN EXIT FUNCTION
        lngRetVal = regqueryvalueex(hkey,"TZI",0,%REG_BINARY,RegTZI,lngSize)
        IF lngRetVal THEN EXIT FUNCTION
        lngRetVal = regclosekey(hkey)
        IF lngRetVal THEN EXIT FUNCTION
        'Populate TZI
        TZI.Bias = RegTZI.Bias
        TZI.StandardBias = RegTZI.StandardBias
        TZI.DaylightBias = RegTZI.DaylightBias
        TZI.STandardDate = RegTZI.STandardDate
        TZI.DaylightDate = RegTZI.DaylightDate
        'Get current time in UTC
         GetSystemTime st1
    
        'Get current local time in TZName
        lngRetVal = SystemTimeToTzSpecificLocalTime(TZI,st1,st2)
    
        'Populate Powertime to use/format time data.
        PT.newdate st2.wyear,st2.wmonth,st2.wday
        PT.newtime st2.whour,st2.wminute,st2.wsecond
        FUNCTION = LEFT$(PT.dayofweekstring,3) & STR$(PT.day) & " " & LEFT$(PT.monthstring,3) & " " & PT.timestring24
    
    END FUNCTION


    Comment


    • #3
      SystemTimeToTzSpecificLocalTime function (timezoneapi.h) - Win32 apps | Microsoft Learn
      might be useful for other than current time and/or other zones.

      Cheers,
      Dale

      Comment


      • #4
        Does the above handle a place like Saskatchewan that doesn't go on Daylight Saving Time? In winter months their time is the same as Manitoba's Central Standard Time. In summer their time is Mountain Daylight Time, same as Alberta to their immediate west. Manitoba is next to Saskatchewan on the east.

        In winter Saskatchewan and Manitoba are an hour east of Alberta, whereas in summer Manitoba is an hour east of Alberta and Saskatchewan.
        Rod
        In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

        Comment


        • #5
          Originally posted by Dale Yarker View Post
          SystemTimeToTzSpecificLocalTime function (timezoneapi.h) - Win32 apps | Microsoft Learn
          might be useful for other than current time and/or other zones.

          Cheers,
          Yep, that's what is used in my code above
          'Get current local time in TZName
          lngRetVal = SystemTimeToTzSpecificLocalTime(TZI,st1,st2)

          But you need to do the TZName lookup in the Registry first to get the details for the appropriate TZI

          Comment


          • #6
            A while ago, I wanted a function that would give me the time in New York. I looked up the 'rules' for Daylight Saving, and wrote the following code (basically, it counts Sundays). BUT... read more at the bottom.

            Code:
            FUNCTION GetFiletimeNYC2 AS QUAD
            
                ' EDT: the time in NYC is UTC-4
                ' EST: the time in NYC is UTC-5
                '
                ' Eastern Daylight Time (EDT) is a North American time zone in use from the second Sunday in March
                ' to the first Sunday in November during Daylight Saving Time (DST). Eastern Standard Time (EST)
                ' is used during the remainder of the year.
                '
                '
                ' Eastern Standard Time Zone
                ' Eastern Standard Time (EST) is a standard time zone in use from the first Sunday in November to
                ' the second Sunday in March—when Daylight Saving Time (DST) is not in effect. Eastern Daylight
                ' Time (EDT) is used during the remainder of the year.
                '
            
                LOCAL i AS IPOWERTIME
                LOCAL CurrentYear AS LONG
                LOCAL CountTheSundays AS LONG
                LOCAL SpringTime AS QUAD
                LOCAL FallTime AS QUAD
                LOCAL UTCTime AS QUAD
                LOCAL DaylightSavingTime AS LONG   ' %TRUE or %FALSE
            
                i = CLASS "PowerTime"
            
                i.NowUTC
            
                UTCTime = i.FileTime
                CurrentYear = i.Year
            
            
                ' ===========================================================================
                ' == find the timestamp of the second Sunday in March of the current year ===
                i.NewDate(CurrentYear, 3, 1)   ' set the date to March 1 of this year     ' =
                i.NewTime(2, 0, 0)             ' at 2:00 AM                               ' =
                i.AddDays(-1)                  ' but then subtract 1 day so it's now      ' =
                                               ' the last day of February                 ' =
                RESET CountTheSundays                                                     ' =
                DO                                                                        ' =
                    i.AddDays(1)                                                          ' =
                    IF LCASE$(i.DayOfWeekString) = "sunday" THEN INCR CountTheSundays     ' =
                LOOP UNTIL CountTheSundays = 2                                            ' =
                SpringTime = i.FileTime                                                   ' =
                ' ===========================================================================
            
            
                ' ===========================================================================
                ' == find the timestamp of the first Sunday in November of the current year =
                i.NewDate(CurrentYear, 10, 31) ' set the date to October 31 of this year  ' =
                i.NewTime(2, 0, 0)             ' at 2:00 AM                               ' =
                RESET CountTheSundays                                                     ' =
                DO                                                                        ' =
                    i.AddDays(1)                                                          ' =
                    IF LCASE$(i.DayOfWeekString) = "sunday" THEN INCR CountTheSundays     ' =
                LOOP UNTIL CountTheSundays = 1                                            ' =
                FallTime = i.FileTime                                                     ' =
                ' ===========================================================================
            
            
            
                IF SpringTime < UTCTime AND UTCTime < FallTime THEN
            
                    ' - it's the summer months
                    ' - Daylight saving is in effect
                    ' - it's EDT
                    DaylightSavingTime = %TRUE
            
                ELSE
            
                    ' - it's NOT the summer months
                    ' - Daylight saving is NOT in effect
                    ' - it's EST
                    DaylightSavingTime = %FALSE
            
                END IF
            
            
            
                i.FileTime = UTCTime
            
                IF ISTRUE  DaylightSavingTime THEN i.AddHours(-4)   ' EDT
                IF ISFALSE DaylightSavingTime THEN i.AddHours(-5)   ' EST
            
                FUNCTION = i.Filetime
            
            END FUNCTION
            
            ​
            The above code makes an ASSUMPTION that the rules about Daylight Savings never change (and beware of assumptions!). For my purposes, it's "good enough" -- for now.

            Be aware that government officials are CONSTANTLY modifying the rules. See here: https://en.wikipedia.org/wiki/Daylig..._United_States

            Lastly, this video is nine years old, but gives an EXCELLENT summary and scope of the problem. It's worth watching... https://youtu.be/-5wpm-gesOY

            EDIT: Rodney, the website timeanddate.com is an excellent source for what timezone rules apply in every specific location on Earth. The webmasters are also good about updating the rules when they change. Again, if you can calculate the difference between your place of interest and UTC, the rest is easy. Here is a link: https://www.timeanddate.com/worldclock/canada/winnipeg

            Last edited by Christopher Becker; 5 May 2023, 12:05 AM. Reason: added a link to timeanddate.com
            Christopher P. Becker
            signal engineer in the defense industry
            Abu Dhabi, United Arab Emirates

            Comment


            • #7
              Originally posted by Rodney Hicks View Post
              Does the above handle a place like Saskatchewan that doesn't go on Daylight Saving Time? In winter months their time is the same as Manitoba's Central Standard Time. In summer their time is Mountain Daylight Time, same as Alberta to their immediate west. Manitoba is next to Saskatchewan on the east.

              In winter Saskatchewan and Manitoba are an hour east of Alberta, whereas in summer Manitoba is an hour east of Alberta and Saskatchewan.
              Presumably yes, since they appear to have their own TZ Name - Canada Central Standard Time:

              Click image for larger version

Name:	Sascatch.jpg
Views:	185
Size:	131.2 KB
ID:	823343

              Comment


              • #8
                Yep, that's what is used in my code above
                Yeap. Insufficient attention to code above because it used IPowerTime. I did go to link to see it was used there, but did not download and open the zip.
                Dale

                Comment


                • #9
                  Originally posted by Christopher Becker View Post
                  The above code makes an ASSUMPTION that the rules about Daylight Savings never change (and beware of assumptions!). For my purposes, it's "good enough" -- for now.

                  Be aware that government officials are CONSTANTLY modifying the rules.
                  To quote MS:
                  "Windows updates the time zones in the registry when time zones are available and updates are downloaded."

                  Comment


                  • #10
                    For a full list of the current Time Zone Names as used by Windows, type tzutil /l at a cmd prompt

                    Comment


                    • #11
                      Originally posted by Dale Yarker View Post
                      because it used IPowerTime.
                      That was just my lazy way of formatting the output as "ddd d mmm hh:nn"

                      Comment


                      • #12
                        Gary> How do world clock builders know if a locale is on/off daylight savings time?

                        Hi Gary,

                        To build a world clock, you could use some time zone registry data.
                        Enumerating HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\ you will get around 130 time zones.
                        Ignore the "Dynamic DST" sub-key, it's not needed unless you want to work with past or sometime future year other than the current one.
                        The data under the value name "TZI" is of type "REG_TZI_FORMAT".
                        It will provide among others the tweaked SYSTEMTIME StandardDate and DaylightDate.
                        These are not real date but the rules to use to get daylight saving date/time and standard date/time.
                        If tzi.wMonth = 0 then Daylight/Standard saving is disabled, else tzi.wDayOfWeek will define a weekday. tzi.wDay will define the week in the month where to find this weekday.
                        For example: 0000-11-01 (DOW = 0) 02:00:00 mean the first sunday of november at 02:00:00
                        0000-03-02 (DOW = 0) 02:00:00 mean the second sunday of march at 02:00:00
                        Note that the year is zero, meaning it's good for current and probably subsequent year, contrary to the "Dynamic DST" sub-key.
                        From this you will have to compute a date for the current year.
                        To know if daylight is in use, one easy way is to compare current date with daylight saving time and standard time.

                        Some APIs that will be useful for this...
                        SystemTimeToTzSpecificLocalTime(), GetLocalTime(), GetSystemTime(), SystemTimeToFileTime(), FileTimeToSystemTime(), GetDateFormat(), GetTimeFormat(), RegOpenKeyEx(), RegQueryValueEx(), RegEnumKeyEx(), RegCloseKey(), SHLoadIndirectString(). If code run only on Win8+ then EnumDynamicTimeZoneInformation() may be used.
                        Last edited by Pierre Bellisle; 8 May 2023, 01:42 AM. Reason: Minor corrections

                        Comment


                        • #13
                          Originally posted by Pierre Bellisle View Post
                          Gary> How do world clock builders know if a locale is on/off daylight savings time?

                          Hi Gary,

                          To build a world clock, you could use some time zone registry data.
                          See post #2

                          Comment


                          • #14
                            I've seen it. It's very elementary. Where does it tell if a locale is on/off daylight savings time?

                            Comment


                            • #15
                              Originally posted by Pierre Bellisle View Post
                              I've seen it. Where does it tell if a locale is on/off daylight savings time?
                              Gary's statement "I still have to account for daylight savings time hour difference to know the local time." was incorrect. As shown, there is no need to know this to determine current time for a locale.
                              But if you really was to know for some reason, it's not that much more work to compare actual time to full Bias.

                              '
                              Code:
                              #COMPILE EXE
                              #DIM ALL
                              %UNICODE = 1
                              #INCLUDE ONCE "WIN32API.INC"
                              
                              TYPE REG_TZI_FORMAT
                                  Bias AS LONG
                                  StandardBias AS LONG
                                  DaylightBias AS LONG
                                  StandardDate AS SystemTime
                                  DaylightDate AS SystemTime
                              END TYPE
                              
                              UNION fqTime
                                  ft AS filetime
                                  qt AS QUAD
                              END UNION
                              
                              FUNCTION PBMAIN() AS LONG
                                  LOCAL lDebug AS LONG: TXT.WINDOW EXE.FULL$, 10,10,45,85 TO lDebug
                                   LOCAL wsTZName AS WSTRING
                                   wsTZName = "GMT Standard Time"
                                   TXT.PRINT  "Current time in " & wsTZName & ":"
                                   TXT.PRINT GetCurrentTimeinZone(wsTZName)
                                   TXT.PRINT
                                   wsTZName = "Aus Eastern Standard Time"
                                   TXT.PRINT  "Current time in " & wsTZName & ":"
                                   TXT.PRINT GetCurrentTimeinZone(wsTZName)
                              
                              
                              'Finalise
                                  TXT.COLOR = %RGB_BLUE
                                  TXT.PRINT
                                  TXT.PRINT "  ....Press any key to exit": TXT.WAITKEY$: TXT.END
                              END FUNCTION
                              
                              FUNCTION GetCurrentTimeinZone (TZName AS WSTRING) AS WSTRING
                                   LOCAL PT AS IPOWERTIME
                                   pt = CLASS "PowerTime"
                                   LOCAL TZI AS TIME_ZONE_INFORMATION
                                   LOCAL RegTZI AS REG_TZI_FORMAT
                                   LOCAL hKey AS DWORD
                                   LOCAL lngRetVal,lngSize AS LONG
                                   LOCAL st1, st2 AS systemtime
                                   LOCAL ft1, ft2 AS fqTime
                                   LOCAL wsDST AS STRING
                                   lngSize = SIZEOF(RegTZI)
                              
                                  'Get TZI info from Registry -
                                  lngRetVal = RegOpenKeyEx(%HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" & TZName,0,%key_query_value,hkey)
                                  IF lngRetVal THEN EXIT FUNCTION
                                  lngRetVal = regqueryvalueex(hkey,"TZI",0,%REG_BINARY,RegTZI,lngSize)
                                  IF lngRetVal THEN EXIT FUNCTION
                                  lngRetVal = regclosekey(hkey)
                                  IF lngRetVal THEN EXIT FUNCTION
                                  'Populate TZI
                                  TZI.Bias = RegTZI.Bias
                                  TZI.StandardBias = RegTZI.StandardBias
                                  TZI.DaylightBias = RegTZI.DaylightBias
                                  TZI.STandardDate = RegTZI.STandardDate
                                  TZI.DaylightDate = RegTZI.DaylightDate
                                  'Get current time in UTC
                                   GetSystemTime st1
                                  'Get current local time in TZName
                                  lngRetVal = SystemTimeToTzSpecificLocalTime(TZI,st1,st2)
                              ' Check for DST
                                  systemtimetofiletime st1, ft1.ft
                                  systemtimetofiletime st2, ft2.ft
                                  SELECT CASE  AS LONG (ft1.qt - ft2.qt) / 600000000 ' current bias in minutes
                                      CASE (RegTZI.Bias + RegTZI.StandardBias )
                                           wsDST = "  -  Currently NOT on DST"
                                       CASE  (RegTZI.Bias + RegTZI.DaylightBias)
                                           wsDST = "  -  Currently on DST"
                                       CASE ELSE
                                           wsDST = "  -  Problem determining  DST"
                                   END SELECT
                              
                               'Populate Powertime to use/format time data.
                                  PT.newdate st2.wyear,st2.wmonth,st2.wday
                                  PT.newtime st2.whour,st2.wminute,st2.wsecond
                                  FUNCTION = LEFT$(PT.dayofweekstring,3) & STR$(PT.day) & " " & LEFT$(PT.monthstring,3) & " " & PT.timestring24 & wsDST
                              END FUNCTION
                              
                              '

                              Comment


                              • #16
                                I've just updated WordTimes in Source Code to display whether a location is on Daylight Time..
                                Using functions developed in previous threads on Windows Time Zones and Modal Inputboxes, a utility to display the current time for any number of locations in different zones. Includes an implementation of a modal input box compiled to a SLL. Feel free to do what you want with the source for your own use - including changing

                                (image at the link)

                                It uses this function:
                                Code:
                                FUNCTION IsDST(TZName AS WSTRING) AS WSTRING
                                     LOCAL ft1,ft2 AS fqTime
                                     LOCAL TZI AS TIME_ZONE_INFORMATION
                                     LOCAL RegTZI AS REG_TZI_FORMAT
                                     LOCAL hKey AS DWORD
                                     LOCAL lngRetVal,lngSize AS LONG
                                     LOCAL st1, st2 AS systemtime
                                     lngSize = SIZEOF(RegTZI)
                                
                                     'Get TZI info from Registry -
                                    lngRetVal = RegOpenKeyEx(%HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" & TZName,0,%key_query_value,hkey)
                                    IF lngRetVal THEN EXIT FUNCTION
                                    lngRetVal = regqueryvalueex(hkey,"TZI",0,%REG_BINARY,RegTZI,lngSize)
                                    IF lngRetVal THEN EXIT FUNCTION
                                    lngRetVal = regclosekey(hkey)
                                    IF lngRetVal THEN EXIT FUNCTION
                                
                                    'Populate TZI
                                    TZI.Bias = RegTZI.Bias
                                    TZI.StandardBias = RegTZI.StandardBias
                                    TZI.DaylightBias = RegTZI.DaylightBias
                                    TZI.STandardDate = RegTZI.STandardDate
                                    TZI.DaylightDate = RegTZI.DaylightDate
                                    'Get current time in UTC
                                     GetSystemTime st1
                                
                                    'Get current local time in TZName
                                    lngRetVal = SystemTimeToTzSpecificLocalTime(TZI,st1,st2)
                                
                                    systemtimetofiletime st1, ft1.ft
                                    systemtimetofiletime st2, ft2.ft
                                    SELECT CASE  AS LONG (ft1.qt - ft2.qt) / 600000000 ' current bias in minutes
                                        CASE (RegTZI.Bias + RegTZI.StandardBias )
                                             FUNCTION = "  -  Currently NOT on DST"
                                         CASE  (RegTZI.Bias + RegTZI.DaylightBias)
                                             FUNCTION = "  -  Currently on DST"
                                         CASE ELSE
                                             FUNCTION = "  -  Problem determining DST"
                                     END SELECT
                                END FUNCTION

                                Comment


                                • #17
                                  GB> How do world clock builders know if a locale is on/off daylight savings time?
                                  SM> Gary's statement "I still have to account for daylight savings time hour difference to know the local time." was incorrect.

                                  It depend on how you compute the time, if SystemTimeToTzSpecificLocalTime() is not used then you might be interested in a way to know the if daylight savings is running.

                                  But the important thing is... it does mean that his question is without interest in any way.

                                  A isDayLightOn() function do not cover the whole story. Saying that DayLight is on or off is wrong if DayLight is disabled wich should be the right answer. Of course a plain isDayLightOn() function is not really needed if you use SystemTimeToTzSpecificLocalTime().

                                  When you wrote "See post #2" first thing that came to my mind is that you didn't read or try to understand my post at all.

                                  A DayLight time saving can be enable-on, enable-off, or disabled and a Standard time can be enable-on, enable-off, or disabled.

                                  As example, California want to adopt perpetual DayLight time.
                                  If this happen you will get a year with a time zone that have a DayLight saving time and a disabled Standard time, aka no Standard time any more.
                                  Subsequent years will have a disabled DayLight and disabled Standard time.

                                  This is why I provided those infos above, for curious people. No problem if you are not interested.
                                  Knowing that the rules like "the first sunday of november at 02:00:00" is embeded in a tweaked tzi is quite interesting. Etc. Etc.
                                  Computing the time change for a year is something that many people want to know.

                                  Your last code will say that DayLight time is off when it can be simply disabled. This is not the same thing.
                                  I guess I will keep using code that try to give the complete picture...

                                  Code:
                                  '____________________________________________________________________________
                                  
                                  %DaylightDateOn       = 1
                                  %StandardDateOn       = 2
                                  %DaylightDateOff      = 4
                                  %StandardDateOff      = 8
                                  %DaylightDateDisabled = 16
                                  %StandardDateDisabled = 32
                                  
                                  FUNCTION TimeZoneTimeChange(regTzi AS REG_TZI_FORMAT) AS DWORD
                                   LOCAL TimeZoneInfo   AS TIME_ZONE_INFORMATION
                                   LOCAL stUtcTime      AS SYSTEMTIME
                                   LOCAL stLocalTime    AS SYSTEMTIME
                                   LOCAL ftUtcTime      AS QUAD 'Aka FILETIME
                                   LOCAL ftLocalTime    AS QUAD 'Aka FILETIME
                                   LOCAL TimeZoneStatus AS DWORD
                                  
                                   TimeZoneInfo.Bias         = regTzi.Bias
                                   TimeZoneInfo.StandardDate = regTzi.StandardDate
                                   TimeZoneInfo.StandardBias = regTzi.StandardBias
                                   TimeZoneInfo.DaylightDate = regTzi.DaylightDate
                                   TimeZoneInfo.DaylightBias = regTzi.DaylightBias
                                  
                                   GetSystemTime(stUtcTime)
                                   SystemTimeToFileTime(stUtcTime, BYVAL VARPTR(ftUtcTime))
                                   SystemTimeToTzSpecificLocalTime(TimeZoneInfo, stUtcTime, stLocalTime)
                                   SystemTimeToFileTime(stLocalTime, BYVAL VARPTR(ftLocalTime))
                                  
                                   'Unusual TimeZone/TimeChange case example:
                                   'Florida may have DaylightDateOn and StandardDateDisabled for one year
                                   'in the future because they want to keep Daylight time and never change time back again,
                                   'meaning both DaylightDate and StandardDate wil be disabled in subsequent years.
                                  
                                   'There is 600,000,000 (100-nanosecond-pack) by minutes in filetime
                                   IF regTzi.StandardDate.wMonth THEN 'Is StandardDate enabled
                                     IF ftUtcTime = ftLocalTime + TimeZoneInfo.Bias * 600000000 + TimeZoneInfo.StandardBias * 600000000 THEN
                                       TimeZoneStatus = %StandardDateOn  'Standard time is now in use in this time zone
                                     ELSE
                                       TimeZoneStatus = %StandardDateOff 'Standard time is now not in use in this time zone
                                     END IF
                                   ELSE 'In fact, every element is usually at zero when disabled, not only .wMonth
                                     TimeZoneStatus = %StandardDateDisabled 'There is no Standard time at all in this time zone
                                   END IF
                                  
                                   IF regTzi.DaylightDate.wMonth THEN 'Is DaylightDate enabled
                                     IF ftUtcTime = ftLocalTime + TimeZoneInfo.Bias * 600000000 + TimeZoneInfo.DaylightBias * 600000000 THEN
                                       TimeZoneStatus OR= %DaylightDateOn  'Daylight saving time is now in use in this time zone
                                     ELSE
                                       TimeZoneStatus OR= %DaylightDateOff 'Daylight saving time is now not in use in this time zone
                                     END IF
                                   ELSE 'In fact, every element is usually at zero when disabled, not only .wMonth
                                     TimeZoneStatus OR= %DaylightDateDisabled 'There is no Daylight time at all in this time zone
                                   END IF
                                  
                                   FUNCTION = TimeZoneStatus
                                  
                                  END FUNCTION
                                  '____________________________________________________________________________
                                  '


                                  Cliquez sur l'image pour la voir en taille réelle   Nom : 		TimeZone.png  Affichages :	1  Taille :		8,9 Ko  ID : 			823436

                                  Comment

                                  Working...
                                  X