Home >
Windows にまつわる e.t.c.
PowerShell で PC 時刻を NTP に合わせる
Windows PC は、NTP から時刻を取得して、自動的に時刻補正をするのですが、PC
の日時が大幅にズレていると時刻同期しない仕様になっています
このため、新しく購入した PC とか、マザーボードのバッテリーを交換した時等で、PC
の日時が大幅に狂っている時は手動で時刻調整をする必要があります
この作業が思いのほか手間なので、NTP から時刻取得して、PC 時刻を調整するスクリプトを書きました
(NTP 実装で
ChatGPT に頑張ってもらったのは内緒です w)
NTP 時刻を取ってくるところは、独立した関数にしていますので、他の用途にも流用できると思います
時刻調整方法
PowerShell を管理者権限で開いて、以下をコピペしてください
時刻調整スクリプトをダウンロードして実行します
$ModuleName = "GetNtpTime" $GitHubName = "MuraAtVwnet" $URI =
"https://raw.githubusercontent.com/$GitHubName/$ModuleName/refs/heads/main/SetNtpTime.ps1"
$OutFile = "~/SetNtpTime.ps1" Invoke-WebRequest -Uri $URI -OutFile
$OutFile & $OutFile
|
GitHub からのスクリプト ダウンロードが失敗する場合
PowerShell を管理者権限で開いて、一番下にあるスクリプトをコピペしてください
オプション
-PreferIPv4
IPv4 を優先する
-Server
NTP Server を指定する
省略時は以下 NTP を使用
ntp.nict.jp
time.google.com
pool.ntp.org
Windows PowerShell を使っている方へ
Windows PowerShell でスクリプトがエラーになって実行出来ない場合は以下コマンドを
PowerShell のプロンプトにコピペしてください
| if((Get-ExecutionPolicy) -ne 'RemoteSigned'){Set-ExecutionPolicy
RemoteSigned -Scope CurrentUser -Force} |
動作確認
Windows PowerShell 5.1
PowerShell 7.5.4 (Windows)
Linux/Mac でも動くとは思いますが、動作確認していません
GitHub
以下リポジトリで公開しています
https://github.com/MuraAtVwnet/GetNtpTime
git@github.com:MuraAtVwnet/GetNtpTime.git
時刻合わせスクリプト
#################################################################
#
# NTP から現在時刻を取得して PC の時刻を修正する
#
#################################################################
#################################################################
# NTP Time 取得
#################################################################
function GetNtpTime {
param(
[string[]]$Server = @("ntp.nict.jp", "time.google.com", "pool.ntp.org"),
[int]$Port = 123,
[int]$TimeoutMs = 3000,
[int]$Retry = 2,
[switch]$PreferIPv4 # IPv4 を優先する
)
function Convert-NtpTimestampToUtc([byte[]]$resp) {
# Transmit Timestamp (bytes 40-47)
$intPart = [BitConverter]::ToUInt32($resp[43..40], 0)
$fracPart = [BitConverter]::ToUInt32($resp[47..44], 0)
$ms = ($intPart * 1000.0) + ($fracPart * 1000.0 / 0x100000000)
$epoch = [DateTime]::SpecifyKind([DateTime]"1900-01-01T00:00:00", [DateTimeKind]::Utc)
$epoch.AddMilliseconds($ms)
}
# NTP request packet (48 bytes)
$req = New-Object byte[] 48
$req[0] = 0x1B
$errors = New-Object System.Collections.Generic.List[string]
foreach ($s in $Server) {
# Resolve all IPs
try {
$ips = [System.Net.Dns]::GetHostAddresses($s)
if (-not $ips -or $ips.Count -eq 0) {
throw "DNS解決結果が空です。"
}
if ($PreferIPv4) {
$ips = @(
$ips | Where-Object { $_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork }
$ips | Where-Object { $_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6 }
)
}
}
catch {
$errors.Add("[$s] DNS解決失敗: $($_.Exception.Message)")
continue
}
foreach ($ip in $ips) {
for ($try = 0; $try -le $Retry; $try++) {
$udp = $null
try {
# UdpClient
$udp = New-Object System.Net.Sockets.UdpClient($ip.AddressFamily)
$udp.Client.ReceiveTimeout = $TimeoutMs
# Windows PowerShell 5.1 でエラーになる対策
$ep = New-Object System.Net.IPEndPoint($ip, $Port)
$udp.Connect($ep)
[void]$udp.Send($req, $req.Length)
$remote = $null
$resp = $udp.Receive([ref]$remote)
if (-not $resp -or $resp.Length -lt 48) {
throw "NTP応答が不正(Length=$($resp.Length))"
}
$utc = Convert-NtpTimestampToUtc $resp
$local = $utc.ToLocalTime()
return [PSCustomObject]@{
Server = $s
Address = $ip.IPAddressToString
UtcTime = $utc
LocalTime = $local
TimeoutMs = $TimeoutMs
Retry = $Retry
}
}
catch {
$errors.Add("[$s / $($ip.IPAddressToString) / try=$try] $($_.Exception.Message)")
}
finally {
if ($udp) { $udp.Close(); $udp.Dispose() }
}
}
}
}
$detail = ($errors | Select-Object -Last 12) -join "`n"
throw "NTP時刻取得に失敗しました。UDP/123遮断 or IPv6/IPv4経路不調の可能性。`n直近のエラー:`n$detail"
}
#################################################################
# main
#################################################################
# PC の時刻を合わせる
Set-Date -Date (GetNtpTime).LocalTime
|


Copyright © MURA
All rights reserved.