Synchronizing Time between a Domain Controller and a client or DC and NTP Server

Every once in awhile something happens that affects the time on the DC, which can have any number of spillover effects to other servers, RODCs, client workstations, even network equipment.
This is the PowerShell script that I use to quickly resolve the issue. Note that it does need to be run in an elevated session.

Write-Host "Available Functions include Fix-Time"
function Fix-Time {
	param (
		$ntpserver
	)

	$computername = (Get-CimInstance win32_computersystem).Name
	$domainMember = (Get-CimInstance -ClassName Win32_ComputerSystem).PartOfDomain
	if ($domainMember -eq $true){
		$domainname = (Get-CimInstance -ClassName Win32_ComputerSystem).Domain
	} else {
		$domainname = (Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object { $_.IPAddress -ne $null } | Select-Object DNSDomain).DNSDomain
	}
	$logonServer = $env:LOGONSERVER
	$logonServer = $logonServer.Substring($logonServer.LastIndexOf("\")+1)
	$fqdn = "$computername.$domainname"
	if ($ntpserver.length -le 0){
		if ((Get-CimInstance Win32_OperatingSystem).ProductType -eq 2){
			$ntpserver = 'north-america.pool.ntp.org'
		} else {
			if ($domainMember -eq $false){
				$ntpserver = w32tm /query /source
			} else {
				$ntpserver = "$logonServer.$domainname"
			}
		}
	}
	$commaIdx = $ntpserver.IndexOf(",")
	if ($commaIdx -ge 0){
		$ntpserver = $ntpserver.Substring(0,$commaIdx)
	}
	Write-Host "Syncronizing time on $computername with $ntpserver"
	$timeExpr = "w32tm.exe /stripchart /computer:$ntpserver /dataonly /samples:1"
	$timeSample = Invoke-Expression $timeExpr
	if (($timeSample.IndexOf("(0x80072AF9)") -ge 0)){
		Write-Host "The provided NTP server, $ntpserver, is unavailable. Please specify a new NTP server and try again, or check network connectivity"  -ForegroundColor Red
		Return
	}
	$td = (($timeSample | Select-Object -Last 1) -split ", " | Select-Object -Last 1)
	if ($fqdn -eq $ntpserver){
		$timedifference = ($td.Substring(1,$td.Length-2))
		if ($td[-1] -eq "s"){
			$timedifference = ($td.Substring(1,$td.Length-2))
		} else {
			Write-Host "An Error has occurred obtaining accurate time. Unable to continue" -ForegroundColor Red
			Return
		}
		if ($timedifference -ge 50){
			$newDate = (Get-Date).AddSeconds($timedifference)
			Set-Date -Date $newDate
		}
	}
	Get-Date
	$timeExpr = "w32tm /config /manualpeerlist:$ntpserver /syncfromflags:manual /reliable:yes /update"
	Invoke-Expression $timeExpr
	Get-Service -Name w32time | Restart-Service
	w32tm /query /status /verbose
	w32tm /query /source
	Get-Date

	
		<#
        .SYNOPSIS
        Synchronizes the time between either an active directory domain's NTP server or a global NTP server

		.DESCRIPTION
        Checks to see if the computer the script is running on is a domain controller, in which case it automatically checks the time against either a default or provided NTP server.
		If the computer is not a domain controller and is a member of a domain then the script checks the time between the local computer and the domain controller.
		If there is a differential between the local computer and the NTP server, updates the local time to be in sync with the server.
		Sunday, January 21, 2024 09:58:14 PM
		w32tm.exe /stripchart /computer:"$ntpserver" /dataonly /samples:1
		The stripchart parameter returns the time offset in seconds 
		Set-Date -Adjust 1:00:00 
		Adjusts the time by one hour. Use a tac to decrease time by the indicated hours, minutes, seconds.
		Must be run from an elevated session.
		
		.PARAMETER 	ntpserver
        Specifies the fqdn of a NTP server to check against. The default is 
		Other examples include 'time.google.com' and 'north-america.pool.ntp.org'

        .INPUTS
        ntpserver paramater

        .OUTPUTS
        System.String. Fix-Time outputs a series of strings about the time information from the NTP server, the offset, and the local CMOS clock.

        .EXAMPLE
        PS> Fix-Time 
        Syncronizing time on MSI with time.windows.com

		Thursday, May 21, 2026 16:31:39
		The command completed successfully.
		Leap Indicator: 0(no warning)
		Stratum: 1 (primary reference - syncd by radio clock)
		Precision: -23 (119.209ns per tick)
		Root Delay: 0.0000000s
		Root Dispersion: 10.0000000s
		ReferenceId: 0x4C4F434C (source name:  "LOCL")
		Last Successful Sync Time: 2026-05-21 16:31:40
		Source: Local CMOS Clock
		Poll Interval: 10 (1024s)

		Phase Offset: 0.0000000s
		ClockRate: 0.0156250s
		State Machine: 0 (Unset)
		Time Source Flags: 0 (None)
		Server Role: 576 (Reliable Time Service)
		Last Sync Error: 1 (The computer did not resync because no time data was available.)
		Time since Last Good Sync Time: 0.2602432s

		Local CMOS Clock
		Thursday, May 21, 2026 16:31:40

        .EXAMPLE
        PS> Fix-Time -ntpserver 'time.google.com'
        Syncronizing time on MSI with time.google.com

		Thursday, May 21, 2026 16:34:21
		The command completed successfully.
		Leap Indicator: 0(no warning)
		Stratum: 1 (primary reference - syncd by radio clock)
		Precision: -23 (119.209ns per tick)
		Root Delay: 0.0000000s
		Root Dispersion: 10.0000000s
		ReferenceId: 0x4C4F434C (source name:  "LOCL")
		Last Successful Sync Time: 2026-05-21 16:34:22
		Source: Local CMOS Clock
		Poll Interval: 10 (1024s)

		Phase Offset: 0.0000000s
		ClockRate: 0.0156250s
		State Machine: 0 (Unset)
		Time Source Flags: 0 (None)
		Server Role: 576 (Reliable Time Service)
		Last Sync Error: 1 (The computer did not resync because no time data was available.)
		Time since Last Good Sync Time: 0.2656827s

		Local CMOS Clock
		Thursday, May 21, 2026 16:34:22

        .LINK
        Online version: https://eclat.tech/software/microsoft/powershell/synchronizing-time-between-a-domain-controller-and-a-client-or-dc-and-ntp-server/
		
		.NOTES
			w32tm doesn't expand the variable name which results in a (0x80072AF9) error that suggests the target computername cannot be found. Turning the expression into a string and using iex resolves this.
			Assumes standard black background console
			Author : Dan Yedinak

		#>

}