LoginSignup
4
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

4
2
0

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
  3. You can use dark theme
What you can do with signing up
4
2