You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
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?
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
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.
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
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.
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
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:
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.
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."
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
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
'
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
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
'____________________________________________________________________________
'
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.
Comment