Zeitzonen - Time Zones

Veröffentliche deine funktionierenden Skripte und Funktionen

Moderator: jNizM

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Zeitzonen - Time Zones

28 Jul 2017, 09:23

Edit: Bugfix in ST2DT() am 29.07.2017. Das Feld für den Wochentag/DayOfWeek in der SYSTEMTIME Struktur hat einen Offset von 4, nicht 0.

Weil wir uns gerade so intensiv mit dem Thema Zeit beschäftigen, kommt hier auch noch ein Skript von mir. Es zeigt die in der Registrierung gespeicherten Daten der einzelnen Zeitzonen an.

Im linken ListView werden der Name des Registrierungsschlüssels für die Zeitzone und die (zumindest zu guten alten XP-Zeiten) angezeigte Beschreibung angezeigt.

Das rechte ListView zeigt die Werte der im linken ListView ausgewählten Zeitzone an:
  • Die erste Zeile enthält die aktuellen Werte inklusive der Daten für die Sommer- bzw. Winterzeit an, sofern es die gibt.
  • Die weiteren Zeilen enthalten die 'dynamischen' Werte für den Fall, dass sich im Laufe der Jahre die Daten der Umstellung verändert haben.
  • Die angezeigten 'Bias' Werte sind Abweichungen von der Universalzeit (UTC) in Minuten. Die angezeigten Daten entsprechen immer der lokale Zeitzone.
Es steht Jedem frei, die in der Klasse enthaltenen Methoden/Funktionen für eigene Zwecke zu missbrauchen oder zu verwurschteln.

Code: Select all

#NoEnv
SetBatchLines, -1
; --------------------------------------------------------------------------------------------------------------------------------
; Read the registry values
TZ := New TimeZones
; --------------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 8, 8
Gui, Add, ListView, xm -Multi w500 r25 vLVReg gLVKey AltSubmit +LV0x14000, Reg Key|Display Name
LocalZone := TZ.Local
LocalRow := 1
For K, V In TZ.Zones {
   Row := LV_Add("", K, V.Display)
   If (K = LocalZone)
      LocalRow := Row
}
LV_ModifyCol(1, "AutoHdr")
LV_ModifyCol(2, "AutoHdr")
Gui, Add, ListView, x+m Grid -Multi w500 r25 vLVDST hwndHLV +LV0x10000
                  , Year|UTC Bias|DST Start|DST Bias|DST End|Std Bias|%A_Space%
LV_Add("", "", "", "0000-00-00 00:00:00", "", "0000-00-00 00:00:00")
Loop, 7
   LV_ModifyCol(A_Index, "AutoHdr")
LV_Delete(1)
LV_ModifyCol(1, "Integer")
LV_ModifyCol(2, "Integer")
LV_ModifyCol(4, "Integer")
LV_ModifyCol(6, "Integer")
Gui, Show, , TimeZones - DST
Gui, ListView, LVReg
LV_Modify(LocalRow, "Focus Select Vis")
Return
; --------------------------------------------------------------------------------------------------------------------------------
GuiClose:
GuiEscape:
ExitApp
; --------------------------------------------------------------------------------------------------------------------------------
LVKey:
Critical
If (A_GuiEvent == "I") && InStr(ErrorLevel, "S", 1) {
   Gui, ListView, LVReg
   LV_GetText(TimeZone, A_EventInfo)
   Current := TZ.Zones[TimeZone, "Current"]
   Dynamic := TZ.Zones[TimeZone, "Dynamic"]
   Gui, ListView, LVDST
   LV_Delete()
   LV_Add("", "", Current.Bias, Current.DltD, Current.DltB, Current.StdD, Current.StdB)
   For DynYear, Values In Dynamic
      LV_Add("", DynYear, Values.Bias, Values.DltD, Values.DltB, Values.StdD, Values.StdB)
}
Return
; --------------------------------------------------------------------------------------------------------------------------------
Class TimeZones {
   __New(P*) {
      Static RegKey := "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
      RegRead, LocalZone, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation, TimeZoneKeyName
      Zones := {}
      ZoneCount := 0
      Loop, Reg, %RegKey%, K
      {
         ZoneCount++
         TimeZone := A_LoopRegName
         RegRead, RegDisp, %RegKey%\%TimeZone%, Display
         RegRead, RegTZI, %RegKey%\%TimeZone%, TZI
         This.ConvertTZI(RegTZI, TZI)
         Current := This.GetValues(&TZI)
         Dynamic := {}
         Loop, Reg, %RegKey%\%TimeZone%\Dynamic DST, V
         {
            If A_LoopRegName Is Date
            {
               DynYear := A_LoopRegName
               RegRead, RegTZI
               This.ConvertTZI(RegTZI, TZI)
               Dynamic[DynYear] := This.GetValues(&TZI, DynYear)
            }
         }
         Zones[TimeZone] := {Display: RegDisp, Current: Current, Dynamic: Dynamic}
      }
      This.Local := LocalZone
      This.Count := ZoneCount
      This.Zones := Zones
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Retrieves the DST values from a REG_TZI_FORMAT structure.
   ; -----------------------------------------------------------------------------------------------------------------------------
   GetValues(Pointer, DynYear := 0) {
      Bias := NumGet(Pointer + 0, "Int")                          ; Bias
      DltD := This.ST2DT(Pointer + 28, DynYear)  ; DaylightDate
      DltB := DltD ? NumGet(Pointer + 8, "Int") : ""              ; DaylightBias
      StdD := This.ST2DT(Pointer + 12, DynYear)  ; StandardDate
      StdB := StdD ? NumGet(Pointer + 4, "Int") : ""              ; StandardBias
      Return {Bias: Bias, DltD: DltD, DltB: DltB, StdD: StdD, StdB: StdB}
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Retrieves a date-time string from a SYSTEMTIME structure using the rules defined for TIME_ZONE_INFORMATION structures.
   ; -> msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
   ; -----------------------------------------------------------------------------------------------------------------------------
   ST2DT(Pointer, DynYear := 0) {
      Year  := NumGet(Pointer + 0, "Short")
      Month := NumGet(Pointer + 2, "Short")
      WDay  := NumGet(Pointer + 4, "Short") + 1
      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 := DynYear ? DynYear : A_YYYY
         Day := This.WDay2Day(Year, Month, WDay, Day)
      }
      Return (Month = 0 ? "" : Format("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", Year, Month, Day, Hour, Min, Sec))
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Calculates the day of the given year and month specified by WDay and occurence.
   ; -----------------------------------------------------------------------------------------------------------------------------
   WDay2Day(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
   }
   ; -----------------------------------------------------------------------------------------------------------------------------
   ; Converts registry TZI values into a REG_TZI_FORMAT structure.
   ; -> msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
   ; -----------------------------------------------------------------------------------------------------------------------------
   ConvertTZI(RegTZI, ByRef TZI) {
      VarSetCapacity(TZI, 44, 0)
      IR := -1
      Addr := &TZI
      Loop, 4  ; Bias - 4 bytes
         Addr := NumPut("0x" . SubStr(RegTZI, IR += 2, 2), Addr + 0, "UChar")
      Loop, 4  ; StandardBias - 4 bytes
         Addr := NumPut("0x" . SubStr(RegTZI, IR += 2, 2), Addr + 0, "UChar")
      Loop, 4  ; DaylightBias - 4 bytes
         Addr := NumPut("0x" . SubStr(RegTZI, IR += 2, 2), Addr + 0, "UChar")
      Loop, 16 ; StandardDate - 16 bytes
         Addr := NumPut("0x" . SubStr(RegTZI, IR += 2, 2), Addr + 0, "UChar")
      Loop, 16 ; DaylightDate - 16 bytes
         Addr := NumPut("0x" . SubStr(RegTZI, IR += 2, 2), Addr + 0, "UChar")
   }
}
Last edited by just me on 28 Jul 2017, 20:39, edited 1 time in total.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Zeitzonen - Time Zones

28 Jul 2017, 20:49

Bugfix in ST2DT() - falsche Distanz (0 statt 4) für den Wochentag/DayOfWeek. Das muss auch in der 'alten' Funktion DateTimeFromSYSTEMTIME() korrigiert werden.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Zeitzonen - Time Zones

07 Aug 2017, 00:36

Ein Schelm, wer Böses dabei denkt... Zufällig kurz danach
http://www.nirsoft.net/utils/time_zones_view.html (01/08/2017)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Zeitzonen - Time Zones

07 Aug 2017, 02:31

Ist doch klar, mit AHK ist man schneller! ;)

Return to “Skripte und Funktionen”

Who is online

Users browsing this forum: No registered users and 19 guests