Retrieve Time Zone information

The GetTimeZoneInformation API returns a TIME_ZONE_INFORMATION variable that contains several pieces of information about system’s time date and time setting. The first Long value in this structure holds the “distance” (in minutes) from Greenwich standard time, so it’s quite easy to create a GetTimeZone function that returns an Integer corresponding to the time zone you’re in:

Private Type SYSTEMTIME    wYear As Integer    wMonth As Integer    wDayOfWeek As Integer    wDay As Integer    wHour As Integer    wMinute As Integer    wSecond As Integer    wMilliseconds As IntegerEnd TypePrivate Type TIME_ZONE_INFORMATION    Bias As Long    StandardName(32) As Integer    StandardDate As SYSTEMTIME    StandardBias As Long    DaylightName(32) As Integer    DaylightDate As SYSTEMTIME    DaylightBias As LongEnd TypePrivate Declare Function GetTimeZoneInformation Lib "kernel32" _    (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long' return the time zone difference from Greenwich Time'' for example +5 for New York, -1 for RomeFunction GetTimeZone() As Single    Dim tzInfo As TIME_ZONE_INFORMATION    GetTimeZoneInformation tzInfo    GetTimeZone = tzInfo.Bias / 60End Function

However, adding the declarations of two UDTs and then using only one of them is a sort of waste, since you only need the value at the beginning of the main UDT. You can make your code much more compact if you use an array of Longs as a buffer. Note that you need a different Declare in order to pass an array of Long instead of the UDT:

Private Declare Function GetTimeZoneInformationAny Lib "kernel32" Alias _    "GetTimeZoneInformation" (buffer As Any) As Long' return the time zone difference from Greenwich Time'' for example -5 for New York, +1 for RomeFunction GetTimeZone() As Single    Dim buffer(0 To 44) As Long    GetTimeZoneInformationAny buffer(0)    GetTimeZone = buffer(0) / -60End Function

UPDATE: This updated version returns a Single value to keep into account those areas that have a fractional time offset, and changes the result of the division to match the value returned by Windows. Thanks to Jared from Adelaide, Australia for spotting these problems with the original routine.UPDATE: Johan Gillis from Belgium has developed a new routine that keeps time zone AND daylight saving time into account. Here’s his routine:

Private Function GetTimeZone() As Single    Dim retval As Long    Dim buffer(0 To 42) As Long     Const TIME_ZONE_ID_INVALID = &HFFFFFFFF    Const TIME_ZONE_ID_UNKNOWN = 0    Const TIME_ZONE_ID_STANDARD = 1    Const TIME_ZONE_ID_DAYLIGHT = 2    retval = GetTimeZoneInformationAny(buffer(0))    Select Case lreturnval       Case TIME_ZONE_ID_INVALID, TIME_ZONE_ID_UNKNOWN           GetTimeZone = 0       Case TIME_ZONE_ID_STANDARD           GetTimeZone = (buffer(0) + buffer(21)) / 60                   'or (tzinfo.bias+tzinfo.standardbias)/60       Case TIME_ZONE_ID_DAYLIGHT           GetTimeZone = (buffer(0) + buffer(42)) / 60                  'or (tzinfo.bias+tzinfo.Daylightbias)/60       Case Else           GetTimeZone = 0    End SelectEnd Function

UPDATE: Kevin Hawkins has proposed an improved version that uses the standard bias when TIME_ZONE_ID_UNKNOWN is returned. Any timezones that do not adjust for daylight savings (like, say Indiana) return TIME_ZONE_ID_UNKNOWN, but that just means that they’re always in the standard offset. Here’s the routine that Kevin proposes:

Private Function GetTimeZone() As Single    Dim retval As Long    Dim buffer(0 To 42) As Long    Const TIME_ZONE_ID_INVALID = &HFFFFFFFF    Const TIME_ZONE_ID_UNKNOWN = 0    Const TIME_ZONE_ID_STANDARD = 1    Const TIME_ZONE_ID_DAYLIGHT = 2    retval = GetTimeZoneInformationAny(buffer(0))    Select Case retval       Case TIME_ZONE_ID_INVALID           GetTimeZone = 0       Case TIME_ZONE_ID_STANDARD, TIME_ZONE_ID_UNKNOWN           GetTimeZone = (buffer(0) + buffer(21)) / 60                  'or (tzinfo.bias+tzinfo.standardbias)/60       Case TIME_ZONE_ID_DAYLIGHT           GetTimeZone = (buffer(0) + buffer(42)) / 60                  'or (tzinfo.bias+tzinfo.Daylightbias)/60       Case Else           GetTimeZone = 0    End SelectEnd Function

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: