LoginSignup
2

More than 5 years have passed since last update.

VBAでUTC時刻・オフセット付き時刻を取得する(WMI使用)

Posted at

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型でローカル時刻を設定できます。

fromLocalvbDate
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を設定できます。

fromUTCvbDate
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プロパティに値を設定します。

fromCIM_DATETIME
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 における時差情報(サマータイム)の取り扱い – とあるコンサルタントのつぶやきより。

WindowsPowerShell
Get-ChildItem -LiteralPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones'

参考

タイムゾーン関連全般の概要

タイムゾーン呪いの書 - Qiita

Windowsにおける時差関係の取り扱い

.NET Framework における時差情報(サマータイム)の取り扱い – とあるコンサルタントのつぶやき

WMI関連情報

SWbemDateTime object | Microsoft Docs
CIM_DATETIME | Microsoft Docs
[WMI Class] Win32_OperatingSystem クラス - WMI Library

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2