PowerShellでローカルタイムとUTCタイムを表示する方法

PowerShellでローカルタイムとUTCタイムを表示する方法を現在の環境で使うなら「current local timeはGet-Date、UTCは(Get-Date).ToUniversalTime()またはDateTimeOffset.UtcNowで取得し、交換用にはISO 8601 round-trip formatを使います。localとUTCを引き算してoffsetを求めず、Get-TimeZoneとDateTimeOffset.Offsetを読みます。」が基本方針です。対象はPowerShell版差に依存しないDateTime.ToUniversalTimeとDateTimeOffsetを中心にするケースです。時刻確認はread-onlyで行い、timezoneやtime serviceの設定変更は別手順にします。

目次

local・UTC・offsetを同じ瞬間から作る

ローカル時刻とUTCを並べる場合は、同じ瞬間からDateTimeOffsetを作り、LocalDateTime、UtcDateTime、Offsetを出力します。端末のTimeZoneInfoと夏時間適用も記録し、文字列を再解析して時刻を作り直しません。UTCとの差がOffsetと一致することを確認すれば、ログ間の時差を安全に換算できます。

  • Get-TimeZoneでIdとBaseUtcOffsetを確認する
  • Get-DateのKindとDateTimeOffset.Now.Offsetを確認する
  • NTP/time service状態は別途確認する
  • log仕様がUTCかoffset付きlocalかを決める

ISO 8601 round-trip形式で表示する

表示は読み取りです。Set-Dateやw32tm resync/configはauthentication、certificate、log順序、clusterへ影響するため、時刻確認の延長で実行しません。変更前にauthoritative time source、domain policy、offset、drift、rollbackを確認します。誤った時刻変更時は管理手順でsourceと同期し、security logを改変しません。

DateTime KindとDateTimeOffsetを区別する

  • localとUTCを別時点で取得して差を計算する
  • BaseUtcOffsetを常にcurrent offsetとする
  • DateTime Kindを見ない
  • format文字列にoffsetを含めない
  • 時刻確認のためSet-Dateする

Windows timezone IDで変換する

localとUTCを同時取得

$now=[DateTimeOffset]::Now
[pscustomobject]@{Local=$now;Utc=$now.UtcDateTime;Offset=$now.Offset;TimeZone=(Get-TimeZone).Id}

同じinstantからlocalとUTCを作ります。

ISO 8601表示

[DateTimeOffset]::Now.ToString('o')
[DateTimeOffset]::UtcNow.ToString('o')

o formatはoffsetとfractionを保持し、machine間交換に適します。

Get-DateからUTCへ

$local=Get-Date
$utc=$local.ToUniversalTime()
$local
$utc

Get-Date -AsUTCの版依存を避けたいscriptで使えます。

指定timezoneへ変換

$utc=[DateTime]::UtcNow
[TimeZoneInfo]::ConvertTimeFromUtc($utc,[TimeZoneInfo]::FindSystemTimeZoneById('Tokyo Standard Time'))

Windows timezone IDを実機で確認します。固定+09:00計算よりDST地域にも対応します。

time serviceを読み取る

w32tm.exe /query /status

権限やservice状態で取得できない場合があります。resyncやconfig変更は別作業です。

w32time同期statusを時刻表示と分ける

DateTime KindがUnspecifiedだと変換時の解釈が曖昧です。DateTimeOffsetはinstantとoffsetを持ちますがtimezone rulesそのものは持ちません。BaseUtcOffsetだけではDST適用中offsetを示さない地域があります。local表示とUTCを別々の瞬間に取得すると微小差があるため、同じDateTimeOffsetから派生します。

timezone変更をせずread-onlyで確認する

UTC clock source、w32tm status、Get-TimeZone、DateTimeOffsetを照合し、DST境界を扱うsystemは既知日時でunit testします。保存logをParseExactまたはDateTimeOffset.Parseで読み戻し、instantが同じか確認します。

UTC・offset・Unix timeの整合を検収する

現在時刻はDateTimeOffset.Nowでinstantとoffsetを一体で取得し、UtcDateTimeまたはToUniversalTimeでUTCへ変換します。表示はISO 8601のo formatを使い、Get-DateのKind不明な値やtimezone変換で二重offsetを加えません。

一つのDateTimeOffsetから四表現を出す

$now=[DateTimeOffset]::Now
[pscustomobject]@{Local=$now.ToString('o');Utc=$now.ToUniversalTime().ToString('o');Offset=$now.Offset;UnixSeconds=$now.ToUnixTimeSeconds()} | Format-List

timezone相違とw32time障害を独立確認する

  • 時刻表現が整合:Local、UTC、Offsetが同じinstantを示し、UTC差がoffsetと一致する
  • 期待timezoneと相違:timezone IDが見つからない場合はUnsupportedZoneとして現在時刻表示と分ける
  • timezone・w32time error:time service query失敗、invalid/ambiguous local timeは同期状態/変換errorとして扱う

画面clockとUTCの文字列差を時刻ずれとみなしません。DST境界では同じlocal表記が二instantを表すことがあるためoffsetを保存します。w32tm statusは同期sourceの補助で、取得時刻そのものとは別です。

DST境界とUTC指定を試す

$zone=[TimeZoneInfo]::FindSystemTimeZoneById('Tokyo Standard Time')
$utc=[DateTime]::UtcNow
[pscustomobject]@{Utc=$utc.ToString('o');Tokyo=[TimeZoneInfo]::ConvertTimeFromUtc($utc,$zone).ToString('yyyy-MM-ddTHH:mm:ss')}

UTC、正/負offset、DST境界、unknown zone、time service unavailableをtestします。ISO local/UTC、offset、timezone ID、Unix time、w32tm source/stratumを保存します。

localとUTCを別々のGet-Dateで取得すると、わずかに異なる瞬間を比較してしまいます。一つのDateTimeOffsetから両方を作り、offsetとtimezone IDを同じ記録へ残します。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次