Link to home
Start Free TrialLog in
Avatar of AlHal2
AlHal2Flag for United Kingdom of Great Britain and Northern Ireland

asked on

More on Time zones in vb 2010

I'm using a Windows 7 machine.  The code below is always exiting the function where it says "Exit do".
Is the subkey correct?  If not, what should it be?

The program will run on a Windows 2012 R2 Standard machine.  Again what should the subkey do?

        Dim hKey, curidx As Integer
        Dim KeyName, KeyValue As String
        Dim s As String
        Dim lResult As Long

        On Error GoTo EnumSubKeysErr

        'SubKey = "Software\Microsoft\Windows NT\CurrentVersion\Time Zones"
        SubKey = "SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
        ' TopKey = "Computer\HKEY_LOCAL_MACHINE"

        lResult = RegOpenKeyEx(TopKey, SubKey, 0, KEY_ALL_ACCESS, hKey)

        MsgBox("lResult = " & lResult)

        EnumSubKeys = hKey
        MsgBox("hkey = " & hKey)
        Do
            KeyName = Space(MAX_SIZE)
            KeyValue = Space(MAX_SIZE)
            If RegEnumKey(hKey, curidx, KeyName, MAX_SIZE) <> ERROR_SUCCESS Then
                Exit Do
            End If
            MsgBox("RegEnumKey = " & RegEnumKey(hKey, curidx, KeyName, MAX_SIZE))
            ReDim Preserve LocTZI(curidx)
            KeyName = StripNulls(KeyName)
            LocTZI(curidx) = GetRegValueLTZI(SubKey & "\" & KeyName)
            curidx = curidx + 1
        Loop
        RegCloseKey(hKey)

Open in new window

Avatar of Scott McDaniel (EE MVE )
Scott McDaniel (EE MVE )
Flag of United States of America image

What are you trying to do with the code?
Avatar of AlHal2

ASKER

For each city, I'm trying to find out the time and it's difference from UK time.
When you say "City", do you mean you have a list of cities, and you need to get their UTC offset?

Or are you trying to get the UTC offset for the machine where your code is running? If you're trying to do that you could use the BaseUTCOffset of a TimeZoneInfo variable:

Dim tzone As TimeZoneInfo = TimeZoneInfo.Local
Dim utc_offset As TimeSpan = tzone.BaseUTCOffset

utc_offset would contain the Offset values, and you could use the various methods of that variable as needed. For example, if you want to know the number of Hours of Offset:

Messagebox.Show(utc_offset.Hours)

https://msdn.microsoft.com/en-us/library/system.timezone.getutcoffset(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.timezoneinfo.baseutcoffset(v=vs.110).aspx
Avatar of AlHal2

ASKER

I could be getting data from anywhere round the world and need to know the time in that place.  Therefore I need a listing of timezones for everywhere.
So you would have a City + Country? Or some other type of data?

Unless you also receive the TimeZone of the "place", or something else you could translate to a TimeZone object, you'll need some way to determine where the UTC of that place would be. Will your data provide you with that?
Avatar of AlHal2

ASKER

The data will have a city name which I can cross reference with the time zone object.
Avatar of AlHal2

ASKER

I'm trying to replicate what happens in this vb6 code.  Does that clarify what I am trying to do?

Public Function GetTZICollection(sRegKey As String) As Boolean
   GetTZICollection = EnumSubKeys(HKLM, sRegKey)
End Function

Private Function EnumSubKeys(TopKey As Long, SubKey As String, Optional colTZ As Collection) As Boolean
   Dim hKey As Long, curidx As Long, KeyName As String, KeyValue As String
   Dim s As String
   RegOpenKeyEx TopKey, SubKey, 0&, KEY_ALL_ACCESS, hKey
   EnumSubKeys = hKey
   Do
     KeyName = Space$(MAX_SIZE)
     KeyValue = Space$(MAX_SIZE)
     If RegEnumKey(hKey, curidx, KeyName, MAX_SIZE) <> ERROR_SUCCESS Then Exit Do
     ReDim Preserve LocTZI(curidx)
     KeyName = StripNulls(KeyName)
     LocTZI(curidx) = GetRegValueLTZI(SubKey & "\" & KeyName)
     curidx = curidx + 1
   Loop
   RegCloseKey hKey
End Function

Private Function GetRegValueLTZI(sKey As String) As LOCALE_TIME_ZONE_INFORMATION
  Dim hKey As Long, ltzi As LOCALE_TIME_ZONE_INFORMATION, sTemp As String
  If RegOpenKeyEx(HKLM, sKey, 0&, KEY_ALL_ACCESS, hKey) <> ERROR_SUCCESS Then Exit Function
 
   Dim lResult As Long
 
 lResult = RegQueryValueEx(hKey, "TZI", 0&, REG_BINARY, ltzi, 44&)
 

  
 
 
  sTemp = Space$(MAX_SIZE)
  
  
  Call RegQueryValueEx(hKey, "Display", 0&, REG_SZ, ByVal sTemp, MAX_SIZE)
  ltzi.DisplayName = StripNulls(sTemp)
  sTemp = Space$(MAX_SIZE)
  Call RegQueryValueEx(hKey, "Std", 0&, REG_SZ, ByVal sTemp, MAX_SIZE)
  ltzi.StandardName = StripNulls(sTemp)
  sTemp = Space$(MAX_SIZE)
  Call RegQueryValueEx(hKey, "Dlt", 0&, REG_SZ, ByVal sTemp, MAX_SIZE)
  ltzi.DaylightName = StripNulls(sTemp)
  sTemp = Space$(MAX_SIZE)
  Call RegQueryValueEx(hKey, "MapID", 0&, REG_SZ, ByVal sTemp, MAX_SIZE)
  ltzi.MapID = StripNulls(sTemp)
  RegCloseKey hKey
  GetRegValueLTZI = ltzi
End Function

Public Function GetRegValueStr(sKey As String, sSubKey As String) As String
  Dim hKey As Long, sTemp As String
  
  GetRegValueStr = ""
  
  Dim agc As Integer
  
  
  agc = RegOpenKeyEx(HKLM, sKey, 0&, KEY_ALL_ACCESS, hKey)
  
  If agc <> ERROR_SUCCESS Then
  
     Exit Function
  
  End If
  
  sTemp = Space$(MAX_SIZE)
  
  If RegQueryValueEx(hKey, sSubKey, 0&, REG_SZ, ByVal sTemp, MAX_SIZE) = ERROR_SUCCESS Then
     
     GetRegValueStr = Trim$(StripNulls(sTemp))
  
  
  End If
  RegCloseKey hKey
End Function

Private Function StripNulls(ByVal sText As String) As String
  Dim nPosition&
  StripNulls = sText
  nPosition = InStr(sText, vbNullChar)
  If nPosition Then StripNulls = Left$(sText, nPosition - 1)
  If Len(sText) Then If Left$(sText, 1) = vbNullChar Then StripNulls = ""
End Function

Public Function UTCToLocalDate(dt As Date, tz As LOCALE_TIME_ZONE_INFORMATION) As Date
   Dim d As Date
   
   Log.WriteLine ("in UTCToLocaldate")
   
   Log.WriteLine ("dt in is " & dt)
   
   Log.WriteLine ("tz.bias info is " & tz.Bias)
   
   Log.WriteLine ("tz.standardbias info is " & tz.StandardBias)
   
      Log.WriteLine ("tz.daylightbias info is " & tz.DaylightBias)
      
       '  Log.WriteLine ("tz.standarddate info is " & tz.StandardDate)
   
    '  Log.WriteLine ("tz.daylightdate info is " & tz.DaylightDate)
   
   
      Log.WriteLine ("tz.displayname info is " & tz.DisplayName)
      
         Log.WriteLine ("tz.standardname info is " & tz.StandardName)
         
            Log.WriteLine ("tz.daylightname info is " & tz.DaylightName)
            
               Log.WriteLine ("tz.mapid info is " & tz.MapID)
   

   
   
   
   
   Log.WriteLine "In UTCToLocalDate"
   
   d = DateSerial(Year(dt), Month(dt), Day(dt)) + TimeSerial(Hour(dt), Minute(dt) - tz.Bias - tz.DaylightBias, Second(dt))
   
   Log.WriteLine "d is " & d
   
   If Not IsDayLight(d, tz) Then
   
       Log.WriteLine "It is not IsDayLight"
      
      d = DateSerial(Year(dt), Month(dt), Day(dt)) + TimeSerial(Hour(dt), Minute(dt) - tz.Bias, Second(dt))
   End If
   UTCToLocalDate = d
   
   
   Log.WriteLine "leaving UTCToLocalDate"
   
End Function

Public Function LocalDateToUTC(dt As Date, tz As LOCALE_TIME_ZONE_INFORMATION) As Date
   
     Log.WriteLine ("in LocaldateToUTC")
   
   Log.WriteLine ("dt in is " & dt)
   
   Log.WriteLine ("tz.bias info is " & tz.Bias)
   
   Log.WriteLine ("tz.standardbias info is " & tz.StandardBias)
   
      Log.WriteLine ("tz.daylightbias info is " & tz.DaylightBias)
      
       '  Log.WriteLine ("tz.standarddate info is " & tz.StandardDate)
   
    '  Log.WriteLine ("tz.daylightdate info is " & tz.DaylightDate)
   
   
      Log.WriteLine ("tz.displayname info is " & tz.DisplayName)
      
         Log.WriteLine ("tz.standardname info is " & tz.StandardName)
         
            Log.WriteLine ("tz.daylightname info is " & tz.DaylightName)
            
               Log.WriteLine ("tz.mapid info is " & tz.MapID)
   
   
   
   If IsDayLight(dt, tz) Then
   
      Log.WriteLine "IsDaylight is true"
        
      LocalDateToUTC = DateSerial(Year(dt), Month(dt), Day(dt)) + TimeSerial(Hour(dt), Minute(dt) + tz.Bias + tz.DaylightBias, Second(dt))
   Else
   
      Log.WriteLine "IsDaylight is false"
   
      LocalDateToUTC = DateSerial(Year(dt), Month(dt), Day(dt)) + TimeSerial(Hour(dt), Minute(dt) + tz.Bias, Second(dt))
   End If
End Function

Private Function IsDayLight(dt As Date, tz As LOCALE_TIME_ZONE_INFORMATION) As Boolean
  Dim dlBegin As Date, dlEnd As Date, date_in As Date
  
  
  Log.WriteLine (" ")
  Log.WriteLine ("In function IsDaylight")
  
  Log.WriteLine ("dt in is " & dt)
  
  date_in = Format(dt, IsDaylight_format)
  
  
  With tz.DaylightDate
       If .wYear Then
          dlBegin = DateSerial(Year(dt), .wMonth, .wDay)
       Else
          dlBegin = WeekDayToDate(Year(dt), .wMonth, .wDayOfWeek, .wDay)
       End If
       dlBegin = dlBegin + TimeSerial(.wHour, .wMinute, .wSecond)
  End With
  
  
  With tz.StandardDate
       If .wYear Then
          dlEnd = DateSerial(Year(dt), .wMonth, .wDay)
       Else
          dlEnd = WeekDayToDate(Year(dt), .wMonth, .wDayOfWeek, .wDay)
       End If
       dlEnd = dlEnd + TimeSerial(.wHour, .wMinute, .wSecond)
  End With
  
  
  Log.WriteLine ("dlbegin is " & dlBegin)
  
  Log.WriteLine ("dlend is " & dlEnd)
  
  Log.WriteLine ("date_in is " & date_in)
  
  
  ' sometimes dlbegin doesn't have a valid date in it.
  ' check by looking for "/" symbol.
  
  If InStr(dlBegin, "/") = 0 Or InStr(dlEnd, "/") = 0 Then
  
  
    Log.WriteLine ("invalid date encountered - assuming not daylight")
  
  
  Else
    
  
  
    If dlBegin < dlEnd Then
  
    Log.WriteLine ("not australia")
  
       If date_in > dlBegin And date_in < dlEnd Then IsDayLight = True
    Else
  
  
    Log.WriteLine ("australia")
  
      'Australia!!!
       If date_in < dlEnd Or date_in > dlBegin Then IsDayLight = True
    End If
  
  End If
  
End Function

Public Function WeekDayToDate(y As Integer, m As Integer, wDay As Integer, nDay As Integer) As Date
  Dim d As Date, n As Integer, s As String, count As Integer, i As Integer
  
  For i = 1 To 31
      d = DateSerial(y, m, i)
      If Month(d) > m Then Exit For
      If wDay = Weekday(d) - 1 Then
         count = count + 1
         WeekDayToDate = d
         If count = nDay Then Exit For
      End If
  Next i
End Function

Public Function IsNT() As Boolean
  Dim verinfo As OSVERSIONINFO
  verinfo.dwOSVersionInfoSize = Len(verinfo)
  If (GetVersionEx(verinfo)) = 0 Then Exit Function
  If verinfo.dwPlatformId = 2 Then IsNT = True
End Function

Open in new window

The two methods I cited earlier do much the same thing in .NET. From what I can gather, that code reads the registry on the machine, and then performs calculations based on those setting. The trouble is that code in .NET retrieves data from the machine where it's run, and then determines the UTC offset.

You won't be able to do that, if all you have is a CITY name. There are many, many Cities with the same name in different regions. For example, in the US, every state has a city named "Springfield", so if all you have is that name, you could not possibly know the time zone for that specific city.

Even if you know more information about that area (the City and State, for US-based addresses) you still cannot know the UTC offset based solely on that. You'd have to keep a table of all cities and such, and then determine the UTC offset from there. There are web services that might provide you what you're after, assuming you have sufficient data to provide the web service.

But you wouldn't search the registry of the local machine to determine UTC offset based on the name of a City.
Avatar of AlHal2

ASKER

My mistake.  We have the names of exchanges / bourses rather than cities.
ASKER CERTIFIED SOLUTION
Avatar of Scott McDaniel (EE MVE )
Scott McDaniel (EE MVE )
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of AlHal2

ASKER

Suppose I'm given the name of a timezone in a config file.  how can I find out how many hours different it is to UK time?
For example the difference between Central European Standard Time will depend on whether the UK is using GMT or BST and whether the other people have their clocks forward or backward.

Also how can I convert this to vb.net
Public Function IsNT() As Boolean
  Dim verinfo As OSVERSIONINFO
  verinfo.dwOSVersionInfoSize = Len(verinfo)
  If (GetVersionEx(verinfo)) = 0 Then Exit Function
  If verinfo.dwPlatformId = 2 Then IsNT = True
End Function

Open in new window

Avatar of AlHal2

ASKER

Thanks.