VBAで時差とかを意識して時間を扱いたい場合にはWMI関連のものが使えそうだったので、備忘録としてメモ。
もっと良い方法があれば指摘していただけると嬉しいです。
SWbemDateTime
のインスタンス
WMI関連のCOMのライブラリMicrosoft WMI Scripting V1.2 Library
内にあるSWbemDateTime
オブジェクトを使用すると、簡単に時刻の変換が行えます。
VBAでインスタンスする場合は以下のように行います。
Microsoft WMI Scripting V1.2 Library
を参照することで型付きで扱うことができます。
Dim wmDate As Object 'As WbemScripting.SWbemDateTime
Set wmDate = CreateObject("WbemScripting.SWbemDateTime")
SWbemDateTimeに時刻を設定する
SWbemDateTimeはインスタンス直後は値が入っていないため、時刻を設定する必要があります。
例として日本標準時で2018年8月12日 12時34分56秒を設定する場合を見てみます。
ローカル時刻から設定
SetVarDate
メソッドにTrueを指定することで、Date型でローカル時刻を設定できます。
Dim localDate As Date
localDate = #8/12/2018 12:34:56 PM#
Call wmDate.SetVarDate(localDate, True)
'Trueは省略可
Call wmDate.SetVarDate(localDate)
UTCから設定
SetVarDate
メソッドにFalseを指定することで、Date型でUTCを設定できます。
Dim utcDate As Date
utcDate = #8/12/2018 3:34:56 AM#
Call wmDate.SetVarDate(utcDate, False)
CIM_DATETIME
形式の文字列から設定
WMI関連のオブジェクトからはyyyymmddHHMMSS.mmmmmmsUUU
の形式(CIM_DATETIME)の文字列として、オフセット付き時刻を取得できます。
この文字列から時刻を設定する場合は、Value
プロパティに値を設定します。
Dim localCIMDate As String
localCIMDate = "20180812123456.000000+540" ' = #8/12/2018 12:34:56 PM#
wmDate.Value = localCIMDate
Dim utcCIMDate As String
utcCIMDate = "20180812033456.000000+000" ' = #8/12/2018 3:34:56 AM#
wmDate.Value = utcCIMDate
SWbemDateTimeから時刻を取得
ローカル時刻として取得
GetVarDate
メソッドにTrueを指定することで、Date型でローカル時刻を取得できます。
Debug.Print wmDate.GetVarDate(True)
'Trueは省略可
Debug.Print wmDate.GetVarDate()
UTCとして取得
GetVarDate
メソッドにFalseを指定することで、Date型でUTCを取得できます。
Debug.Print wmDate.GetVarDate(False)
CIM_DATETIME
として取得
Value
プロパティからCIM_DATETIMEを取得できます。
Debug.Print wmDate.Value
おまけ
オフセット(UTCからの時差)の取得
SWbemDateTimeのUTC
プロパティから分単位でオフセットを取得できます。
現在時刻をCIM_DATETIMEとして取得
WMIのOS情報から直接引っ張ってくる関数。
SWbemLocator
さえ取得してしまえば、後は型情報が保持される(入力補完がつながる)ので1ステートメントで取得。
Function GetCIM_DATETIME() As String
Const LocalDateTime = "LocalDateTime"
Const WQL = "SELECT " & LocalDateTime & " FROM Win32_OperatingSystem"
Dim locator As Object 'As WbemScripting.SWbemLocator
Set locator = VBA.CreateObject("WbemScripting.SWbemLocator")
Let GetCIM_DATETIME = _
locator.ConnectServer().ExecQuery(WQL) _
.ItemIndex(0).Properties_ _
.Item(LocalDateTime).Value
End Function
WMIのOS情報一覧表示
上記関数作成時の情報確認に使ったもの。
Sub printOSInfoByWMI()
Dim locator As Object 'As WbemScripting.SWbemLocator
Set locator = VBA.CreateObject("WbemScripting.SWbemLocator")
Dim services As Object 'As WbemScripting.SWbemServices
Set services = locator.ConnectServer()
Dim objSet As Object 'As WbemScripting.SWbemObjectSet
Set objSet = services.ExecQuery("SELECT * FROM Win32_OperatingSystem")
Dim osInfo As Object 'As WbemScripting.SWbemObjectEx
Set osInfo = objSet.ItemIndex(0)
Dim prop As Object 'As WbemScripting.SWbemProperty
For Each prop In osInfo.Properties_
Debug.Print prop.Name, ;
If prop.IsArray Then
Debug.Print VBA.Join(prop.Value, ",")
Else
Debug.Print prop.Value
End If
Next prop
Stop
End Sub
レジストリのタイムゾーンの一覧
.NET Framework における時差情報(サマータイム)の取り扱い – とあるコンサルタントのつぶやきより。
Get-ChildItem -LiteralPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones'
参考
タイムゾーン関連全般の概要
Windowsにおける時差関係の取り扱い
WMI関連情報
SWbemDateTime object | Microsoft Docs
CIM_DATETIME | Microsoft Docs
[WMI Class] Win32_OperatingSystem クラス - WMI Library