Posted at

HTTP経由でのNTP時刻合わせ(PowerShell利用)

More than 3 years have passed since last update.

Firewall に囲まれてて NTP が通らないので書いた。

HTTP(S)で日本標準時を文字列で返してくれるサービスが提供されているのでそちらを利用、対象 OS が Linux 系なら wget を使えばいいけど Windows にはそんなものは(標準では)無いので PowerShell から .NET を呼び出してどうにかする。


コード


ntpdate.ps1

# 管理者権限で実行すること

$ntpdatestring = (new-object System.Net.WebClient).DownloadString("http://ntp-a1.nict.go.jp/cgi-bin/time").Replace(" JST", " +0900").Trim()
$datetime = [DateTime]::ParseExact($ntpdatestring, "ddd MMM dd HH:mm:ss yyyy zzzz", [Globalization.CultureInfo]::CreateSpecificCulture("en-US"))

set-date $datetime


あとはタスクスケジューラにぶち込んだりすれば良いのでは。定時ダッシュの精度が高まりますね


実装時にはまった点

PowerShell 初めて書いた& そもそも .NET あんまり知らんのでそもそも全部ハマっ

WebClient#DownloadString() が 返す文字列の後ろに謎の改行文字が入ってることに気付かなくてパース出来なかった

DateTime#ParseExact() の時にロケール…じゃなくてカルチャに en-US を指定をしないといけない(自環境だとデフォルトのカルチャが ja-JP になるので ddd は "日曜" だの "月曜" だのが有効な値、"Sun" やら "Mon" は認識出来ない)ことに気付くのに大分時間が掛かった


NTPリソース

日本標準時プロジェクト 公開NTP サービス対応クライアントリスト

日本標準時プロジェクト https/http を介してアクセスされる場合

/cgi-bin/time は RFC1123 形式っぽいけど少し違う

/cgi-bin/ntp と /cgi-bin/jst は text/plain じゃないのでアレ


環境

OS: Windows 7 Pro


Windows PowerShell

Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\> $PSVersionTable

Name Value


CLRVersion 2.0.50727.5485

BuildVersion 6.1.7601.17514

PSVersion 2.0

WSManStackVersion 2.0

PSCompatibleVersions {1.0, 2.0}

SerializationVersion 1.1.0.1

PSRemotingProtocolVersion 2.1



書いてから気付いたけど PowerShell で JSON 読めるならそれ使ったほうが楽だったのでは…?

JSON 使えるやん…

→ PowerShell 3.0 からだった。Windows 7 デフォルトは V2 なのである意味セーフ

st に UNIX 時間が入ってるから new DateTime(1970, 1, 1, 9, 0, 0) に AddSeconds() で良いのかなー