Getting current timezone on windows

Okay. This is the closest I can get in windows. Now it will show the countries as displayed in timezone settings for windows. I have just added two properties to be displayed in the code.

Will display: b Amsterdam, Berlin, Bern, Rome, Stockholm, vienna[/b] for my timezone, same as windows

[code]
// This example will get the computer system running Windows timezone
//http://library.wmifun.net/cimv2/win32_timezone.html

//http://msdn.microsoft.com/en-us/library/aa394498(v=vs.85).aspx

Dim locator, objWMIService, objs, objProperty As OLEOBJECT
Dim nobjs as Integer

// Connect to WMI
locator = new oleObject(“WbemScripting.SWbemlocator”, true)

Dim wmiServiceParams(2) as variant
wmiServiceParams(1) = “.”
wmiServiceParams(2) = “root\cimv2”

objWMIService= locator.invoke(“ConnectServer”, wmiServiceParams)

// Run the WMI query
objs = objWMIService.ExecQuery (“SELECT * FROM Win32_TimeZone”)

nobjs = objs.count - 1

For i as integer = 0 to nobjs
Dim stringData As String

objProperty = objs.ItemIndex(i)
// ItemIndex() is not supported in Windows XP only from Windows Vista and upwards

stringData = "DaylightName: "  + objProperty.Value("DaylightName") + EndOfLine
stringData = stringData + "TimeZone: "  + objProperty.Value("StandardName") + EndOfLine
stringData = stringData + "Description: "  + objProperty.Value("Description") + EndOfLine
stringData = stringData + "Caption: "  + objProperty.Value("Caption") + EndOfLine
msgbox stringData

Next

locator = Nil

exception err as oleexception
msgbox err.message[/code]

[quote=82688:@John Hansen]Okay. This is the closest I can get in windows. Now it will show the countries as displayed in timezone settings for windows. I have just added two properties to be displayed in the code.

Will display: b Amsterdam, Berlin, Bern, Rome, Stockholm, vienna[/b] for my timezone, same as windows

[code]
// This example will get the computer system running Windows timezone
//http://library.wmifun.net/cimv2/win32_timezone.html

//http://msdn.microsoft.com/en-us/library/aa394498%28v=vs.85%29.aspx

Dim locator, objWMIService, objs, objProperty As OLEOBJECT
Dim nobjs as Integer

// Connect to WMI
locator = new oleObject(“WbemScripting.SWbemlocator”, true)

Dim wmiServiceParams(2) as variant
wmiServiceParams(1) = “.”
wmiServiceParams(2) = “root\cimv2”

objWMIService= locator.invoke(“ConnectServer”, wmiServiceParams)

// Run the WMI query
objs = objWMIService.ExecQuery (“SELECT * FROM Win32_TimeZone”)

nobjs = objs.count - 1

For i as integer = 0 to nobjs
Dim stringData As String

objProperty = objs.ItemIndex(i)
// ItemIndex() is not supported in Windows XP only from Windows Vista and upwards

stringData = "DaylightName: "  + objProperty.Value("DaylightName") + EndOfLine
stringData = stringData + "TimeZone: "  + objProperty.Value("StandardName") + EndOfLine
stringData = stringData + "Description: "  + objProperty.Value("Description") + EndOfLine
stringData = stringData + "Caption: "  + objProperty.Value("Caption") + EndOfLine
msgbox stringData

Next

locator = Nil

exception err as oleexception
msgbox err.message[/code][/quote]

Great. This displays the same information as my method by another way :slight_smile:

Congratulations, John.

PS : Too bad it’s not good enough for the OP :confused:

[quote=82691:@Michel Bujardet] Great. This displays the same information as my method by another way :slight_smile:

Congratulations, John.

PS : Too bad it’s not good enough for the OP :/[/quote]

No. Your code display different timezone on my windows Vista: (UTC +01:00) Brussels, Copenhagen, Madrid, Paris

And when I check the timezone settings in “Change time and date settings” i have it set to: b Amsterdam, Berlin, Bern, Rome, Stockholm, vienna[/b]

I wonder if your code get the Systems default timezone and mine get users current timezone

The IANA has the db + code to use the db which could be ported
Hence why I suggested getting it from the authority that maintains the DB & code

Still it will be hard to get the name right unless you have both the gmt offset & long / lat as there are numerous that resolve to the same GMT offset and then you have to use the current long / lat to know which location to show

[quote=82693:@John Hansen]No. Your code display different timezone on my windows Vista: UTC +01:11) Brussels, Copenhagen, Madrid, Paris

And when I check the timezone settings in “Change time and date settings” i have it set to: (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, vienna[/quote]

You are right. Your method better reflect the settings in the Control Panel. I tried to change to vastly different places like Port Louis, and the change is accurate, while the registry information I was pulling does not change.

Bravo !

This gonna be interesting :slight_smile:

OK. I looked at the way Windows actually stores the time zone information. My first method did not work at all.

What Windows does is to store the time zone area name in a key, and then the cities within another key with the area name. This new method now displays the area, then the cities. That is probably the closest I will ever get to what the OP wanted, except for Windows, an area has several cities. And it is impossible to guess which one should be picked.

For instance, it will display :

West Asia Standard Time (UTC+05:00) Ashgabat, Tashkent

One could easily parse the information to show it in Tz Database format with the city values as :
Asia/Ashgabat
Asia/Tashkent

Code :

[code] // get a registry key
Dim reg As New RegistryItem(“HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation”)
Dim TimeZ As String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = “TimeZoneKeyName” then
TimeZ = reg.Value(i)
exit
end if
Next

reg = New RegistryItem("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"+TimeZ)
Dim TimeCities as String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = “Display” then
TimeCities = reg.Value(i)
exit
end if
Next

// and display the time zone as cities
MsgBox TimeZ+EndOfLine+TimeCities
[/code]

Christian, adding a property to your class will probably mean providing several cities, as the Tz Database data for one city only is not there.

[quote=82702:@Michel Bujardet]OK. I looked at the way Windows actually stores the time zone information. My first method did not work at all.

What Windows does is to store the time zone area name in a key, and then the cities within another key with the area name. This new method now displays the area, then the cities. That is probably the closest I will ever get to what the OP wanted, except for Windows, an area has several cities. And it is impossible to guess which one should be picked.

For instance, it will display :

West Asia Standard Time
(UTC+05:00) Ashgabat, Tashkent

One could easily parse the information to show it in Tz Database format with the city values as :
Asia/Ashgabat
Asia/Tashkent

Code :

// get a registry key
Dim reg As New RegistryItem(“HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation”)
Dim TimeZ As String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = “TimeZoneKeyName” then
TimeZ = reg.Value(i)
exit
end if
Next

reg = New RegistryItem(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones”+TimeZ)
Dim TimeCities as String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = “Display” then
TimeCities = reg.Value(i)
exit
end if
Next

// and display the time zone as cities
MsgBox TimeZ+EndOfLine+TimeCities[/quote]

Congratulations Michel. Yours code is better to use as it will also works on Windows XP :slight_smile: . Mine Not :frowning:

John, I am afraid I must disappoint you – just tried with XP SP3, no luck :frowning:

What about using Xojo shell class and “systeminfo” - XP onwards i think.

Dim s As Shell = New Shell s.TimeOut = -1 Dim TimeZone as string = "systeminfo | find"+" "+"""Time Zone""" s.Execute(TimeZone) MsgBox(s.Result)

It does not work under XP SP3. Systeminfo is unrecognized.

I just had a look at what is going on in XP.

The name of the key that points to the area key is different. “StandardName” instead of “TimeZoneKeyName”. After modifying the line in the first loop of my method, it does provide the correct data.

So to get this method to work in all versions of Windows including XP, it will be necessary to detects XP and make that change.

Dave Sysemore has posted a nice method for that at
https://forum.xojo.com/2239-how-to-determine-os-which-version-and-which-ver-of-windoz

How odd Microsoft says so?

http://technet.microsoft.com/en-us/library/bb491007.aspx

[quote=82777:@Lee Page]How odd Microsoft says so?

http://technet.microsoft.com/en-us/library/bb491007.aspx[/quote]

Proof is in the pudding. Windows XP SP3 line of command reply when I enter systeminfo :
‘systeminfo’ is not recognized as an internal or external command, operable program or batch file.

Abundance of documentation does not mean bug free. There is no Paul Lefebvre at MS. And they do not have a Feedback app :wink:

On the other hand, systeminfo and your shell do work fine under Windows 8.1 64 bit. It does provide the cities information, but not the area.

i run the same Windows XP SP3 and i got results…but then i am running it under virtual box

My Windows XP SP3 is under a VM as well (VMWare Fusion). But I doubt that would make any difference with a real PC. Looks more like inconsistency between releases. At any rate, this shows that MS documentation cannot be taken for granted. If an app had been released using a shell to systeminfo, it would have quickly experienced frustrated user support requests…

[quote=82741:@Michel Bujardet] John Hansen Congratulations Michel. Yours code is better to use as it will also works on Windows XP :slight_smile: . Mine Not :frowning:

John, I am afraid I must disappoint you – just tried with XP SP3, no luck :([/quote]

I did a test on my Notebook with Windows XP SP3. Didn’t work. (tested with RS2012R2.1)

Yep me too. Looks as though the systeminfo command is not included in XP home edition (I did get command not found) and certain OEM distro’s.

For me personally I am no longer going to waste code development time targeting XP unless it is a specific project for a client but I very much doubt that will happen.

Best place for XP is the “recycle bin” :slight_smile:

Michel I believe I found the problem for WIndows XP.
My windows XP SP3 don’t have this key name: TimeZoneKeyName. Changed it to “StandardName” then it works

  // get a registry key
  Dim reg As New RegistryItem("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\TimeZoneInformation")
  Dim TimeZ As String
  // now we look on all values on this key
  For i As Integer = 0 To reg.KeyCount- 1
    Dim name As String = reg.Name(i)
    Dim value As Variant = reg.Value(i)
    //if name = "TimeZoneKeyName" then  // this part is not working on every Windows XP SP3 Computer
    if name = "StandardName" then
      TimeZ = reg.Value(i)
      exit
    end if
  Next
  
  reg = New RegistryItem("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\"+TimeZ)
  Dim TimeCities as String
  // now we look on all values on this key
  For i As Integer = 0 To reg.KeyCount- 1
    Dim name As String = reg.Name(i)
    Dim value As Variant = reg.Value(i)
    if name = "Display" then
      TimeCities = reg.Value(i)
      exit
    end if
  Next
  
  // and display the time zone as cities
  MsgBox(Timez + EndOfLine+TimeCities)

But on Windows 7 Pro “StandardName” has key value: “@tzrez.dll, -322” Then I will need to use “TimeZoneKeyName”

Yes. I mentioned it above. You found the problem. Congratulations.

I have since incorporated in the project Dave Sysemore method of detecting the Windows version :

[code]Function GetVersion() As string
#If TargetWin32

dim OS as string  = "Windows"
dim OS_CODE as integer

//try to be more specific of windows version
Soft Declare Sub GetVersionExA Lib "Kernel32" ( info As Ptr )
Soft Declare Sub GetVersionExW Lib "Kernel32" ( info As Ptr )

Dim info As MemoryBlock

If System.IsFunctionAvailable( "GetVersionExW", "Kernel32" ) Then
  info =  New MemoryBlock( 20 + (2 * 128) )
  info.Long( 0 ) = info.Size
  GetVersionExW( info )
Else
  info =  New MemoryBlock( 148 )
  info.Long( 0 ) = info.Size
  GetVersionExA( info )
End If

Dim Str As String
OS_CODE=info.Long(4)*100+info.long(8)
Select Case OS_CODE
Case 400
  os = "Windows 95/NT 4.0"
Case 410
  os = "Windows 98"
Case 490
  os = "Windows Me"
Case 300 To 399
  os = "Windows NT 3.51"
  OS_CODE=30
Case 500
  os = "Windows 2000"
Case 501
  os = "Windows XP"
Case 502
  os = "Windows Server 2003"
Case 600
  os = "Windows Vista"
Case 601
  os = "Windows 7"
Case 602
  os = "Windows 8"
End Select
Str = " Build " + Str( info.Long( 12 ) )

If System.IsFunctionAvailable( "GetVersionExW", "Kernel32" ) Then
  Str = Str + " " + Trim( info.WString( 20 ) )
Else
  Str = Str + " " + Trim( info.CString( 20 ) )
End If

os = os + Str
Return os

#EndIf
End Function
[/code]

Now the method works on both XP and earlier, and reads as :

[code] Sub Action()
if not TargetWin32 then return
dim tzname as string
dim os as string = GetVersion
if instr(os, “Windows XP”)>0 then
tzname = “StandardName”
elseif instr(os, “Windows 95/NT 4.0”)>0 or instr(os, “Windows 98”)>0 or instr(os, “Windows Me”)>0 then
return
else
tzname = “TimeZoneKeyName”
end if

// get a registry key
Dim reg As New RegistryItem("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation")
Dim TimeZ As String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = tzname then
TimeZ = reg.Value(i)
exit
end if
Next

reg = New RegistryItem("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"+TimeZ)
Dim TimeCities as String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = “Display” then
TimeCities = reg.Value(i)
exit
end if
Next

// and display the time zone as cities
MsgBox TimeZ+EndOfLine+TimeCities

End Sub
[/code]

Thanks to the OP for an interesting challenge…

[quote=82863:@Michel Bujardet]Yes. I mentioned it above. You found the problem. Congratulations.

I have since incorporated in the project Dave Sysemore method of detecting the Windows version :

[code]Function GetVersion() As string
#If TargetWin32

dim OS as string  = "Windows"
dim OS_CODE as integer

//try to be more specific of windows version
Soft Declare Sub GetVersionExA Lib "Kernel32" ( info As Ptr )
Soft Declare Sub GetVersionExW Lib "Kernel32" ( info As Ptr )

Dim info As MemoryBlock

If System.IsFunctionAvailable( "GetVersionExW", "Kernel32" ) Then
  info =  New MemoryBlock( 20 + (2 * 128) )
  info.Long( 0 ) = info.Size
  GetVersionExW( info )
Else
  info =  New MemoryBlock( 148 )
  info.Long( 0 ) = info.Size
  GetVersionExA( info )
End If

Dim Str As String
OS_CODE=info.Long(4)*100+info.long(8)
Select Case OS_CODE
Case 400
  os = "Windows 95/NT 4.0"
Case 410
  os = "Windows 98"
Case 490
  os = "Windows Me"
Case 300 To 399
  os = "Windows NT 3.51"
  OS_CODE=30
Case 500
  os = "Windows 2000"
Case 501
  os = "Windows XP"
Case 502
  os = "Windows Server 2003"
Case 600
  os = "Windows Vista"
Case 601
  os = "Windows 7"
Case 602
  os = "Windows 8"
End Select
Str = " Build " + Str( info.Long( 12 ) )

If System.IsFunctionAvailable( "GetVersionExW", "Kernel32" ) Then
  Str = Str + " " + Trim( info.WString( 20 ) )
Else
  Str = Str + " " + Trim( info.CString( 20 ) )
End If

os = os + Str
Return os

#EndIf
End Function
[/code]

Now the method works on both XP and earlier, and reads as :

[code] Sub Action()
if not TargetWin32 then return
dim tzname as string
dim os as string = GetVersion
if instr(os, “Windows XP”)>0 then
tzname = “StandardName”
elseif instr(os, “Windows 95/NT 4.0”)>0 or instr(os, “Windows 98”)>0 or instr(os, “Windows Me”)>0 then
return
else
tzname = “TimeZoneKeyName”
end if

// get a registry key
Dim reg As New RegistryItem(“HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation”)
Dim TimeZ As String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = tzname then
TimeZ = reg.Value(i)
exit
end if
Next

reg = New RegistryItem(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones”+TimeZ)
Dim TimeCities as String
// now we look on all values on this key
For i As Integer = 0 To reg.KeyCount- 1
Dim name As String = reg.Name(i)
Dim value As Variant = reg.Value(i)
if name = “Display” then
TimeCities = reg.Value(i)
exit
end if
Next

// and display the time zone as cities
MsgBox TimeZ+EndOfLine+TimeCities

End Sub
[/code]

Thanks to the OP for an interesting challenge…[/quote]

Oops… Missed that post. Could have saved me some time If I read the thread more carefully :slight_smile:

Well done Michel