I'm looking for a way, perhaps via the Winapi, it doesn't have to be,
to get the DST (daylight-saving time) start/end dates/times
for my local time zone (or time zones generally) in UTC.
I have written a function that does this for my local time zone,
but I want to confirm that it is accurate.
Note:
GetTimeZoneInformationForYear looked like it might be promising,
however, what it puts into the SYSTEMTIME structure appears
not to be a date, but a rule, possibly copied from the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
I could use such information to calculate the dates,
but what I want to do is check that my existing function works correctly,
not create another function that might also have errors in it.
TYFR
get DST (daylight-saving time) start/end dates/times in UTC
get DST (daylight-saving time) start/end dates/times in UTC
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: get DST (daylight-saving time) start/end dates/times in UTC
As far as I understand the rules:
I couldn't find out how to set the values of PDYNAMIC_TIME_ZONE_INFORMATION to retrieve the information for other than the local time zone as yet.
Edit: Fixed a bug in TZI_GetWDayInMonth()
Code: Select all
; ----------------------------------------------------------------------------------------------------------------------------------
; Requires Win Vista+
; ----------------------------------------------------------------------------------------------------------------------------------
#NoEnv
Year := 2015
TZI := TZI_GetFromYear(Year)
Gui, Add, ListView, w1000 r9, Field|Value|Description
LV_Add("", "Bias", TZI.Bias, "Minutes (UTC = Local Time + Bias).")
LV_Add("", "StandardName", TZI.StandardName
, "A description for standard time.")
LV_Add("", "StandardDate", TZI.StandardDate
, "A date and local time when the transition from daylight saving time to standard time occurs on this operating system.")
LV_Add("", "StandardDate (UTC)", TZI.StandardDateUTC
, "Calculated UTC date and time.")
LV_Add("", "StandardBias", TZI.StandardBias
, "This value is added to the value of the Bias member to form the bias used during standard time.")
LV_Add("", "DaylightName", TZI.DaylightName
, "A description for daylight saving time.")
LV_Add("", "DaylightDate", TZI.DaylightDate
, "A date and local time when the transition from standard time to daylight saving time occurs on this operating system.")
LV_Add("", "DaylightDate (UTC)", TZI.DaylightDateUTC
, "Calculated UTC date and time.")
LV_Add("", "DaylightBias", TZI.DaylightBias
, "This value is added to the value of the Bias member to form the bias used during daylight saving time.")
Loop, 3
LV_ModifyCol(A_Index, "AutoHdr")
Gui, Show, , TZI for %Year%
Return
GuiClose:
GuiEscape:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------------------
; GetTimeZoneInformationForYear -> msdn.microsoft.com/en-us/library/bb540851(v=vs.85).aspx (Win Vista+)
; ----------------------------------------------------------------------------------------------------------------------------------
TZI_GetFromYear(Year) {
If Year Is Not Integer
Return 0
If Year Is Not Date
Return 0
Year := SubStr(Year, 1, 4)
VarSetCapacity(TZI, 172, 0)
If !DllCall("GetTimeZoneInformationForYear", "UShort", Year, "Ptr", 0, "Ptr", &TZI, "Int")
Return 0
R := {}
R.Bias := NumGet(TZI, "Int")
R.StandardName := StrGet(&TZI + 4, 32, "UTF-16")
ST := New TZI_SYSTEMTIME(&TZI + 68)
; If ST.Year is not zero the date is fix. Otherwise, the date is variable and must be calculated.
; ST.WDay contains the weekday and ST.Day the occurrence within ST.Month (5 = last) in this case.
If (ST.Year = 0) {
ST.Year := Year
ST.Day := TZI_GetWDayInMonth(ST.Year, ST.Month, ST.WDay, ST.Day)
}
R.StandardDate := ST.TimeStamp
R.StandardBias := NumGet(TZI, 84, "Int")
R.DaylightName := StrGet(&TZI + 88, 32, "UTF-16")
ST := New TZI_SYSTEMTIME(&TZI + 152)
If (ST.Year = 0) {
ST.Year := Year
ST.Day := TZI_GetWDayInMonth(ST.Year, ST.Month, ST.WDay, ST.Day)
}
R.DaylightDate := ST.TimeStamp
R.DaylightBias := NumGet(TZI, 168, "Int")
; Calculate the UTC values for StandardDate and DaylightDate
UTCBias := R.Bias + R.DaylightBias ; StandardDate
UTCDate := R.StandardDate
UTCDate += UTCBias, M
R.StandardDateUTC := UTCDate
UTCBias := R.Bias + R.StandardBias ; DaylightDate
UTCDate := R.DaylightDate
UTCDate += UTCBias, M
R.DaylightDateUTC := UTCDate
Return R
}
; ----------------------------------------------------------------------------------------------------------------------------------
TZI_GetWDayInMonth(Year, Month, WDay, Occurence) {
YearMonth := Format("{:04}{:02}01", Year, Month) ; bugfix
If YearMonth Is Not Date
Return 0
If WDay Not Between 1 And 7
Return 0
If Occurence Not Between 1 And 5 ; 5 = last occurence
Return 0
FormatTime, WD, %YearMonth%, WDay
While (WD <> WDay) {
YearMonth += 1, D
FormatTime, WD, %YearMonth%, WDay
}
While (A_Index <= Occurence) && (SubStr(YearMonth, 5, 2) = Month) {
Day := SubStr(YearMonth, 7, 2)
YearMonth += 7, D
}
Return Day
}
; ----------------------------------------------------------------------------------------------------------------------------------
Class TZI_SYSTEMTIME {
__New(Pointer) { ; a pointer to a SYSTEMTIME structure
This.Year := NumGet(Pointer + 0, "Short")
This.Month := NumGet(Pointer + 2, "Short")
This.WDay := NumGet(Pointer + 4, "Short") + 1 ; DayOfWeek is 0 (Sunday) thru 6 (Saturday) in the SYSTEMTIME structure
This.Day := NumGet(Pointer + 6, "Short")
This.Hour := NumGet(Pointer + 8, "Short")
This.Min := NumGet(Pointer + 10, "Short")
This.Sec := NumGet(Pointer + 12, "Short")
This.MSec := NumGet(Pointer + 14, "Short")
}
TimeStamp[] { ; TimeStamp YYYYMMDDHH24MISS
Get {
Return Format("{:04}{:02}{:02}{:02}{:02}{:02}", This.Year, This.Month, This.Day, This.Hour, This.Min, This.Sec)
}
Set {
Return ""
}
}
}
Edit: Fixed a bug in TZI_GetWDayInMonth()
Re: get DST (daylight-saving time) start/end dates/times in UTC
Well done, you've done an excellent job here, thank you.
You'll most likely know that you can use data from here in the meantime for other time zones:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
and here for the local one:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
Yes, you had the same problem as me, it puts a rule not a date into the SYSTEMTIME structure, and you've worked out from that what the dates should be. This is nice, it gives me another source not written by me for date checking.
I'm still interested in *any* methods for getting the DST start/end dates/times for my local time zone (or time zones generally) in UTC. Any software or websites might be interesting also. Cheers.
I will post some related code after further checking.
You'll most likely know that you can use data from here in the meantime for other time zones:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
and here for the local one:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
Yes, you had the same problem as me, it puts a rule not a date into the SYSTEMTIME structure, and you've worked out from that what the dates should be. This is nice, it gives me another source not written by me for date checking.
I'm still interested in *any* methods for getting the DST start/end dates/times for my local time zone (or time zones generally) in UTC. Any software or websites might be interesting also. Cheers.
I will post some related code after further checking.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: get DST (daylight-saving time) start/end dates/times in UTC
To anyone who can help. I'm still interested in getting the time now for other countries/time zones, via DllCall or RegRead, and also via the Internet. And also, the dates at which DST begins/ends, for a particular country/time zone, via similar methods. Thanks.
Note: the items in the registry re. dates, the DST begin/end dates, can be a bit hard to decipher.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
HKEY_CURRENT_USER\Control Panel\International
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language
Note: the items in the registry re. dates, the DST begin/end dates, can be a bit hard to decipher.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
HKEY_CURRENT_USER\Control Panel\International
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language
Last edited by jeeswg on 27 Jul 2017, 03:38, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: get DST (daylight-saving time) start/end dates/times in UTC
@Bobo: Can you access that in AHK? (I did try.)
I have since found out, that for dealing with the registry directly, the key to the problem is the _REG_TZI_FORMAT struct, listed towards the bottom of this link:
TIME_ZONE_INFORMATION structure (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
I should be able to use the registry to get the time zone information and thus create a script later, although DllCall (e.g. specify a time zone by name and retrieve a struct containing its info) and Internet solutions (e.g. a website that returns JSON for a city) would still be worthwhile.
I have since found out, that for dealing with the registry directly, the key to the problem is the _REG_TZI_FORMAT struct, listed towards the bottom of this link:
TIME_ZONE_INFORMATION structure (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
I should be able to use the registry to get the time zone information and thus create a script later, although DllCall (e.g. specify a time zone by name and retrieve a struct containing its info) and Internet solutions (e.g. a website that returns JSON for a city) would still be worthwhile.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: get DST (daylight-saving time) start/end dates/times in UTC
https://gist.github.com/ykessler/3349960e.g. a website that returns JSON for a city
https://en.wikipedia.org/wiki/Tz_database
Re: get DST (daylight-saving time) start/end dates/times in UTC
This will show you some of the current time zone information stored in the registry:
Also, there's an old script which might still work.
Code: Select all
#NoEnv
; ----------------------------------------------------------------------------------------------------------------------
RegRoot := "HKEY_LOCAL_MACHINE"
RegKey := "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
RegTimeZones := {}
; ----------------------------------------------------------------------------------------------------------------------
; Read the registry values
Loop, %RegRoot%, %RegKey%, 2
{
RegRead, DSP, %RegRoot%, %RegKey%\%A_LoopRegName%, Display
RegRead, REGTZI, %RegRoot%, %RegKey%\%A_LoopRegName%, TZI
TZI2TIMEZONEINFORMATION(REGTZI, TIMEZONEINFORMATION)
DSDT := DateTimeFromSYSTEMTIME(&TIMEZONEINFORMATION + 152)
STDT := DateTimeFromSYSTEMTIME(&TIMEZONEINFORMATION + 68)
RegTimeZones[A_LoopRegName] := [DSP, DSDT, STDT]
}
; ----------------------------------------------------------------------------------------------------------------------
Gui, Margin, 20, 20
Gui, Add, ListView, xm Grid -Multi w800 r20 vLV hwndHLV, RegName|DisplayName|DST Start|DST End
Gui, Add, Statusbar
For Key, Value In RegTimeZones
LV_Add("", Key, Value*)
Loop, 4
LV_ModifyCol(A_Index, "AutoHdr")
Gui, Show, , Timezones - DST
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
GuiEscape:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
TZI2TIMEZONEINFORMATION(TZI, ByRef TIMEZONEINFORMATION) {
; Convert registry TZI values into TIMEZONEINFORMATION struct
Bias := 0 ; Bias
StdD := 68 ; StandardDate
StdB := 84 ; StandardBias
DltD := 152 ; DaylightDate
DltB := 168 ; DaylightBias
VarSetCapacity(TIMEZONEINFORMATION, 172, 0)
IR := -1
Addr := &TIMEZONEINFORMATION + Bias ; Bias
Loop, 4
Addr := NumPut("0x" . SubStr(TZI, IR += 2, 2), Addr + 0, "UChar")
Addr := &TIMEZONEINFORMATION + StdB ; StandardBias
Loop, 4
Addr := NumPut("0x" . SubStr(TZI, IR += 2, 2), Addr + 0, "UChar")
Addr := &TIMEZONEINFORMATION + DltB ; DaylightBias
Loop, 4
Addr := NumPut("0x" . SubStr(TZI, IR += 2, 2), Addr + 0, "UChar")
Addr := &TIMEZONEINFORMATION + StdD ; StandardDate
Loop, 16
Addr := NumPut("0x" . SubStr(TZI, IR += 2, 2), Addr + 0, "UChar")
Addr := &TIMEZONEINFORMATION + DltD ; DaylightDate
Loop, 16
Addr := NumPut("0x" . SubStr(TZI, IR += 2, 2), Addr + 0, "UChar")
}
; ----------------------------------------------------------------------------------------------------------------------
DateTimeFromSYSTEMTIME(Pointer) {
Year := NumGet(Pointer + 0, "Short")
Month := NumGet(Pointer + 2, "Short")
Day := NumGet(Pointer + 6, "Short")
Hour := NumGet(Pointer + 8, "Short")
Min := NumGet(Pointer + 10, "Short")
Sec := NumGet(Pointer + 12, "Short")
If (Year = 0) && (Month <> 0) {
Year := A_YYYY
Day := GetWDayInMonth(Year, Month, NumGet(Pointer + 0, "Short") + 1, Day)
}
Return (Month = 0 ? "" : Format("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", Year, Month, Day, Hour, Min, Sec))
}
; ----------------------------------------------------------------------------------------------------------------------------------
GetWDayInMonth(Year, Month, WDay, Occurence) {
YearMonth := Format("{:04}{:02}01", Year, Month)
If YearMonth Is Not Date
Return 0
If WDay Not Between 1 And 7
Return 0
If Occurence Not Between 1 And 5 ; 5 = last occurence
Return 0
FormatTime, WD, %YearMonth%, WDay
While (WD <> WDay) {
YearMonth += 1, D
FormatTime, WD, %YearMonth%, WDay
}
While (A_Index <= Occurence) && (SubStr(YearMonth, 5, 2) = Month) {
Day := SubStr(YearMonth, 7, 2)
YearMonth += 7, D
}
Return Day
}
Re: get DST (daylight-saving time) start/end dates/times in UTC
Not sure if this link is also useful -> Microsoft Time Zone Index Values (msdn)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: get DST (daylight-saving time) start/end dates/times in UTC
Check if it's DST in the current time zone:
==================================================
A function similar to GetWDayInMonth above, which instead uses some Mod maths:
Note: it returns a date, rather than the day of the month.
Explanation of the maths:
Note: the Winapi uses 0=Sun to 6=Sat, AHK uses 1=Sun to 7=Sat, this does not affect the calculations.
==================================================
Get information about all the time zones in the registry:
@just me: Nice example.
@jNizM: Cheers.
Code: Select all
q:: ;is it DST in current time zone
VarSetCapacity(TIME_ZONE_INFORMATION, 172, 0)
;TIME_ZONE_ID_DAYLIGHT := 2 ;TIME_ZONE_ID_STANDARD := 1
;TIME_ZONE_ID_UNKNOWN := 0 ;'Daylight saving time is not used'
vIsDST := (DllCall("GetTimeZoneInformation", Ptr,&TIME_ZONE_INFORMATION, UInt) = 2)
MsgBox, % vIsDST
return
A function similar to GetWDayInMonth above, which instead uses some Mod maths:
Note: it returns a date, rather than the day of the month.
Code: Select all
;where vWDay (Sun=1, Sat=7)
;where vOcc = 5 means Last
JEE_DateGetNthWDayInMonth(vYear, vMonth, vWDay, vOcc)
{
vDate := Format("{:04}{:02}", vYear, vMonth)
FormatTime, vWDay2, % vDate, WDay
vDate += Mod(7+vWDay-vWDay2,7)+(vOcc-1)*7, Days
if !(SubStr(vDate, 5, 2) = vMonth)
vDate += -7, Days
return vDate
}
Note: the Winapi uses 0=Sun to 6=Sat, AHK uses 1=Sun to 7=Sat, this does not affect the calculations.
Code: Select all
jump from first day of month, to first Sunday of month:
Sun(0) + 0 = Sun
Mon(1) + 6 = Sun
Tue(2) + 5 = Sun
Wed(3) + 4 = Sun
Thu(4) + 3 = Sun
Fri(5) + 2 = Sun
Sat(6) + 1 = Sun
n + Mod(7-n) = Sun
jump from first day of month, to first Monday of month:
Sun(0) + 1 = Mon
Mon(1) + 0 = Mon
Tue(2) + 6 = Mon
Wed(3) + 5 = Mon
Thu(4) + 4 = Mon
Fri(5) + 3 = Mon
Sat(6) + 2 = Mon
n + Mod(7+1-n,7) = Mon
jump from first day of month, to first XXXday of month:
n + Mod(7+x-n,7) = XXX
starting from vDate, the first day of the month:
and where vWDay corresponds to the weekday of vDate:
- jump from first day of month, to first Sunday of month:
vDate += Mod(7-vWDay,7), Days
- jump from first day of month, to first Monday of month:
vDate += Mod(7+1-vWDay,7), Days
- jump from first day of month, to first XXX-day of month:
vDate += Mod(7+vDayOfWeek-vWDay,7), Days
Get information about all the time zones in the registry:
Code: Select all
q:: ;get time zone information
vYear := SubStr(A_NowUTC, 1, 4)
Loop, Reg, HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones, K
vList .= A_LoopRegName "`n"
vList := SubStr(vList, 1, -1)
Sort, vList
Loop, Parse, vList, `n
{
vTimeZoneKeyName := A_LoopField
RegRead, vIsObsolete, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, IsObsolete
;if vIsObsolete
; continue
RegRead, vDisplay, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, Display
RegRead, vDlt, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, Dlt
RegRead, vStd, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, Std
RegRead, vHex, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName "\Dynamic DST", % vYear
RegRead, vFirstEntry, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName "\Dynamic DST", FirstEntry
RegRead, vLastEntry, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName "\Dynamic DST", LastEntry
vSpecificYear := (vHex = "") ? "_" : "Y"
if (vHex = "")
RegRead, vHex, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, TZI
vOffset1 := RegExReplace(vDisplay, "\(UTC|:|\).*")
if (vOffset1 = "")
vOffset1 := "+0000"
vOffset2 := Format("{:04}", 1200 + vOffset1)
vChars := 88, vSize := 44
;CRYPT_STRING_HEX := 0x4
;CRYPT_STRING_HEXRAW := 0xC ;(not supported by Windows XP)
DllCall("crypt32\CryptStringToBinary", Ptr,&vHex, UInt,vChars, UInt,0x4, Ptr,0, UIntP,vSize, Ptr,0, Ptr,0)
VarSetCapacity(REG_TZI_FORMAT, vSize, 0)
DllCall("crypt32\CryptStringToBinary", Ptr,&vHex, UInt,vChars, UInt,0x4, Ptr,®_TZI_FORMAT, UIntP,vSize, Ptr,0, Ptr,0)
vBias := NumGet(REG_TZI_FORMAT, 0, "Int") ;Bias
vStandardBias := NumGet(REG_TZI_FORMAT, 4, "Int") ;StandardBias
vDaylightBias := NumGet(REG_TZI_FORMAT, 8, "Int") ;DaylightBias
;StandardDate and DaylightDate:
Loop, 2
{
vOffset := ®_TZI_FORMAT + (A_Index=1?12:28)
vMonth := NumGet(vOffset+0, 2, "Short") ;wMonth
vDayOfWeek := NumGet(vOffset+0, 4, "Short") ;wDayOfWeek ;XXXday
vDay := NumGet(vOffset+0, 6, "Short") ;wDay ;e.g. 1=first XXXday of month, 5=last XXXday of month
vHour := NumGet(vOffset+0, 8, "Short") ;wHour
vMinute := NumGet(vOffset+0, 10, "Short") ;wMinute
vMonth%A_Index% := Format("{:02}", vMonth)
vNthWDay := StrSplit("First,Second,Third,Fourth,Last", ",")[vDay]
;10/01/1904 was a Sun (weekday index to name)
FormatTime, vDDDD, % 1904011 vDayOfWeek, dddd
FormatTime, vDDD, % 1904011 vDayOfWeek, ddd
FormatTime, vMMMM, % 1900 Format("{:02}", vMonth), MMMM
FormatTime, vMMM, % 1900 Format("{:02}", vMonth), MMM
vDate := vNthWDay " " vDDDD " " vMMMM " " Format("{:02}:{:02}:00", vHour, vMinute)
vDateX := vNthWDay " " vDDD " " vMMM " " Format("{:02}:{:02}", vHour, vMinute)
if (vDate = " Sunday " " 00:00:00")
vDate := vDateX := "(none)"
vDate%A_Index% := vDate
vDateX%A_Index% := vDateX
vYears := vFirstEntry ? (vFirstEntry "-" vLastEntry) : ""
}
vOutput .= ""
. vDisplay
. "`r`n" vStd
. "`r`n" vDlt
. "`r`n" vDate1
. "`r`n" vDate2
. "`r`n`r`n"
;M: DST during middle of year, E: DST during ends (start/end) of year
vType := (vMonth1) > (vMonth2) ? "M" : (vMonth1) < (vMonth2) ? "E" : "_"
vOutput2 .= vType vSpecificYear "|" vOffset2 "|" vOffset1 "|" vStd "|" vDlt "|" vDisplay "|" vDateX1 "|" vDateX2 "|" vYears "`r`n"
}
Clipboard := SubStr(vOutput, 1, -2) "`r`n" vOutput2
MsgBox, % "done"
return
@jNizM: Cheers.
Last edited by jeeswg on 29 Jul 2017, 00:41, edited 4 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: get DST (daylight-saving time) start/end dates/times in UTC
Multiple (digital) clocks for different countries, that update simultaneously:
Code: Select all
;show clocks for various time zones:
;UTC, local, New York, London, Paris, Munich
#SingleInstance force
vYear := SubStr(A_NowUTC, 1, 4)
vUseMui := 0
if vUseMui
{
vPath := "C:\Windows\System32\tzres.dll"
hModule := DllCall("kernel32\LoadLibrary", "Str",vPath, "Ptr")
vPfx := "MUI_"
}
else
vPfx := ""
vTemp := 0
SetTimer, UpdateTimestamps, 1000
(oTemp := {}).SetCapacity(200)
(oArray := {}).SetCapacity(200)
;note: registry loop retrieves items in reverse order
Loop Reg, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones", % "K"
{
vTimeZoneKeyName := A_LoopRegName
RegRead, vIsObsolete, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, IsObsolete
if vIsObsolete
continue
RegRead, vDisplay, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, % vPfx "Display"
if vUseMui
{
vNum := RegExReplace(vDisplay, ".*-")
VarSetCapacity(vDisplay, 1024)
DllCall("user32\LoadString", "Ptr",hModule, "UInt",vNum, "Str",vDisplay, "Int",1024)
}
else
vNum := RegExReplace(vDisplay, "\(UTC|\+|:|\).*")
;note: vNum will be used to sort items
(vNum = "") && (vNum := 0)
oTemp.Push((vNum+50000) vDisplay)
;oArray[vDisplay] := vTimeZoneKeyName
oArray[vDisplay] := JEE_TimeZoneGetInfo(vTimeZoneKeyName, vYear, vUseMui)
InStr(vDisplay, "(UTC)") && (vDisplayUTC := vDisplay)
InStr(vDisplay, "Eastern Time") && (vDisplayNewYork := vDisplay)
InStr(vDisplay, "London") && (vDisplayLondon := vDisplay)
InStr(vDisplay, "Paris") && (vDisplayParis := vDisplay)
InStr(vDisplay, "Berlin") && (vDisplayMunich := vDisplay)
}
vOutput := ""
VarSetCapacity(vOutput, 10000*2)
Loop % oTemp.Length()
vOutput .= oTemp[oTemp.Length()+1-A_Index] "|"
Sort, vOutput, D|
vOutput := RegExReplace(vOutput, "(^|\|)\K.{5}")
RegRead, vTimeZoneKeyName, HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation, TimeZoneKeyName
RegRead, vDisplay, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, Display
vOptGUI := "w700"
vFontSize1 := "s15"
vFontSize2 := "s20"
oDDL := []
oDDL.1 := StrReplace(vOutput, vDisplayUTC "|", vDisplayUTC "||")
oDDL.2 := StrReplace(vOutput, vDisplay "|", vDisplay "||")
oDDL.3 := StrReplace(vOutput, vDisplayNewYork "|", vDisplayNewYork "||")
oDDL.4 := StrReplace(vOutput, vDisplayLondon "|", vDisplayLondon "||")
oDDL.5 := StrReplace(vOutput, vDisplayParis "|", vDisplayParis "||")
oDDL.6 := StrReplace(vOutput, vDisplayMunich "|", vDisplayMunich "||")
for vKey, vValue in oDDL
{
Gui, Font, % vFontSize1
Gui, Add, DropDownList, % vOptGUI, % vValue
Gui, Font, % vFontSize2
Gui, Add, Text, % vOptGUI
}
Gui, Show,, time zones
return
;==================================================
UpdateTimestamps:
vTemp++
WinGet, hWnd, ID, time zones ahk_class AutoHotkeyGUI
vNow := A_NowUTC
if !(vYear = SubStr(vNow, 1, 4))
{
Reload
return
}
Loop 6
{
vDate := vNow
ControlGetText, vText, % "ComboBox" A_Index, % "ahk_id " hWnd
vTemp := ((vDate < oArray[vText].date1) || (vDate >= oArray[vText].date2)) ? 1 : 2
EnvAdd, vDate, % -oArray[vText, "offset" vTemp], Minutes
vTimeZone := oArray[vText, "name" vTemp]
FormatTime, vDate, % vDate, ddd yyyy-MM-dd HH:mm:ss
ControlSetText, % "Static" A_Index, % vDate " " vTimeZone, % "ahk_id " hWnd
}
return
;==================================================
JEE_TimeZoneGetInfo(vTimeZoneKeyName, vYear:="", vUseMui:=0)
{
local
static vIsReady := 0, vPfx := ""
if vUseMui & !vIsReady
{
vPath := "C:\Windows\System32\tzres.dll"
hModule := DllCall("kernel32\LoadLibrary", "Str",vPath, "Ptr")
vPfx := "MUI_"
vIsReady := 1
}
(vYear = "") && (vNow := A_NowUTC, vYear := SubStr(vNow, 1, 4))
RegRead, vDlt, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, % vPfx "Dlt"
RegRead, vStd, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, % vPfx "Std"
RegRead, vHex, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName "\Dynamic DST", % vYear
if (vHex = "")
RegRead, vHex, % "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" vTimeZoneKeyName, TZI
if vUseMui
{
vNum := RegExReplace(vDlt, ".*-")
VarSetCapacity(vDlt, 1024)
DllCall("user32\LoadString", "Ptr",hModule, "UInt",vNum, "Str",vDlt, "Int",1024)
vNum := RegExReplace(vStd, ".*-")
VarSetCapacity(vStd, 1024)
DllCall("user32\LoadString", "Ptr",hModule, "UInt",vNum, "Str",vStd, "Int",1024)
}
vChars := 88, vSize := 44
;CRYPT_STRING_HEX := 0x4
;CRYPT_STRING_HEXRAW := 0xC ;(not supported by Windows XP)
DllCall("crypt32\CryptStringToBinary", "Ptr",&vHex, "UInt",vChars, "UInt",0x4, "Ptr",0, "UInt*",vSize, "Ptr",0, "Ptr",0)
VarSetCapacity(REG_TZI_FORMAT, vSize, 0)
DllCall("crypt32\CryptStringToBinary", "Ptr",&vHex, "UInt",vChars, "UInt",0x4, "Ptr",®_TZI_FORMAT, "UInt*",vSize, "Ptr",0, "Ptr",0)
vBias := NumGet(®_TZI_FORMAT, 0, "Int") ;Bias
vBias2 := NumGet(®_TZI_FORMAT, 4, "Int") ;StandardBias
vBias1 := NumGet(®_TZI_FORMAT, 8, "Int") ;DaylightBias
;StandardDate and DaylightDate:
Loop 2
{
vOffset := ®_TZI_FORMAT + (A_Index=1?12:28)
vMonth := NumGet(vOffset+0, 2, "Short") ;wMonth
vDayOfWeek := NumGet(vOffset+0, 4, "Short") ;wDayOfWeek ;XXXday
vDay := NumGet(vOffset+0, 6, "Short") ;wDay ;e.g. 1=first XXXday of month, 5=last XXXday of month
vHour := NumGet(vOffset+0, 8, "Short") ;wHour
vMinute := NumGet(vOffset+0, 10, "Short") ;wMinute
vDate := Format("{:04}{:02}01{:02}{:02}00", vYear, vMonth, vHour, vMinute)
FormatTime, vWDay, % vDate, WDay
EnvAdd, vDate, % Mod(8+vDayOfWeek-vWDay,7)+(vDay-1)*7, Days
EnvAdd, vDate, % vBias + vBias%A_Index%, Minutes
if !(SubStr(vDate, 5, 2) = vMonth)
EnvAdd, vDate, -7, Days
vDate%A_Index% := vDate
(vMonth = 0) && (vBias%A_Index% := 0)
}
oArray := {}
;date1 is date DST ends, date2 is date DST starts,
;offset1 is offset when not DST, offset2 is offset when is DST
if (vDate1 < vDate2) ;period between dates is not DST
oArray := {date1:vDate1, date2:vDate2, offset1:vBias+vBias1, offset2:vBias+vBias2, name1:vDlt, name2:vStd}
else ;period between dates is DST
oArray := {date1:vDate2, date2:vDate1, offset1:vBias+vBias2, offset2:vBias+vBias1, name1:vStd, name2:vDlt}
return oArray
}
;==================================================
;links (registry keys/structs/MUI):
;_TIME_ZONE_INFORMATION | Microsoft Docs
;https://docs.microsoft.com/en-us/windows/desktop/api/timezoneapi/ns-timezoneapi-_time_zone_information
;DYNAMIC_TIME_ZONE_INFORMATION (timezoneapi.h) | Microsoft Docs
;https://docs.microsoft.com/en-gb/windows/desktop/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information
;Dynamic daylight saving time provides support for time zones whose boundaries for daylight saving time change from year to year.
;Multilingual User Interface - Windows applications | Microsoft Docs
;https://docs.microsoft.com/en-gb/windows/desktop/Intl/multilingual-user-interface
;registry keys:
;HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
;HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
;structs:
;[size: 172]
;typedef struct _TIME_ZONE_INFORMATION {
; LONG Bias;
; WCHAR StandardName[32];
; SYSTEMTIME StandardDate;
; LONG StandardBias;
; WCHAR DaylightName[32];
; SYSTEMTIME DaylightDate;
; LONG DaylightBias;
;} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
;[size: 44]
;typedef struct _REG_TZI_FORMAT
;{
; LONG Bias;
; LONG StandardBias;
; LONG DaylightBias;
; SYSTEMTIME StandardDate;
; SYSTEMTIME DaylightDate;
;} REG_TZI_FORMAT;
;==================================================
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 9
- Joined: 23 Nov 2016, 16:39
Re: get DST (daylight-saving time) start/end dates/times in UTC
Ok, I'm a little late on the reply but I cannot not reply to jeeswg's answer:
Code: Select all
;show clocks for various time zones:
;UTC, local, New York, London, Paris, Munich
;Everybody talk about Pop Muzik
;https://www.youtube.com/watch?v=gPoiv0sZ4s4
Who is online
Users browsing this forum: Araphen and 366 guests