function Get-NtpTime { # A function that sends UDP packets to NTP server # via IPv4 or IPv6 to obtain the precise time. # # return: datetime (based local timezone) # $null (no server or something went wrong) param([string]$NtpServer) try { # NTP packet (48 bytes) $ntpData = New-Object byte[] 48 $ntpData[0] = 0x1B # Send to ntp server via 123/UDP $addresses = [System.Net.Dns]::GetHostAddresses($NtpServer) $udpClient = $null foreach ($addr in $addresses) { try { $udpClient = New-Object System.Net.Sockets.UdpClient($addr.AddressFamily) $endpoint = New-Object System.Net.IPEndPoint($addr, 123) $udpClient.Connect($endpoint) # Received a response [void]$udpClient.Send($ntpData, $ntpData.Length) $udpClient.Client.ReceiveTimeout = 1500 $response = $udpClient.Receive([ref]$endpoint) if ($response) { $udpClient.Close() break } } catch { $udpClient.Close() $udpClient = $null } } if (-not $udpClient) { return $null } # NTP timestamps are stored in bytes 40-47 (based on January 1, 1900) $intPart = [BitConverter]::ToUInt32(($response[43..40]), 0) $fracPart = [BitConverter]::ToUInt32(($response[47..44]), 0) $ms = ($fracPart * 1000) / 0x100000000 $secondsSince1900 = $intPart $unixEpochOffset = 2208988800 $unixSeconds = $secondsSince1900 - $unixEpochOffset $dateTime = (Get-Date "1970-01-01T00:00:00Z").AddSeconds($unixSeconds).AddMilliseconds($ms) return $dateTime.ToLocalTime() } catch { return $null } } # End of function Get-NtpTime # Usage Examples Get-NtpTime -NtpServer "time.windows.com" Get-NtpTime -NtpServer "ntp.nict.jp"