Public/Network/Get-NtpDate.ps1

Function Get-NtpDate {
  <#
.SYNOPSIS
    To get the time from an NTP server
.DESCRIPTION
    To get the time from an NTP server.
 
    Will return a [DateTime] and accepts the -Verbose parameter. If request fails it will return "1/1/1900"
.PARAMETER ComputerName
    The name or IPv4 address of the computer running NTP. Aliased to 'CN', 'Server', 'NtpServer'
.PARAMETER Port
    The port number NTP is listening to. Defaults to 123
.EXAMPLE
    Get-NtpDate $DC
    Assuming $DC holds the name of the domain controller then would return a datetime similar to
    Monday, March 05, 2018 9:52:57 AM
.OUTPUTS
    [datetime]
#>

  [CmdletBinding()]
  Param (
    [parameter(Mandatory, HelpMessage = 'Add help message for user',
      ValueFromPipeline,
      Position = 0)]
    [Alias('CN', 'Server', 'NtpServer')]
    [string] $ComputerName,

    [int] $Port = 123
  )

  begin {
    Write-Invocation $MyInvocation
    Out-Verbose "Attempting to get time from NTP server $ComputerName"
    $oldEA = $ErrorActionPreference
    $ErrorActionPreference = 'Stop'
  }

  process {
    $Socket = New-Object -TypeName Net.Sockets.Socket -ArgumentList ( 'InterNetwork', 'Dgram', 'Udp' )
    $Socket.SendTimeOut = 2000  # ms
    $Socket.ReceiveTimeOut = 2000  # ms
    try {
      $Socket.Connect( $ComputerName, $Port )
      $NTPData = New-Object -TypeName byte[] -ArgumentList 48
      $NTPData[0] = 27 # Request header: 00 = No Leap Warning; 011 = Version 3; 011 = Client Mode; 00011011 = 27
      $Socket.Send(    $NTPData ) | Out-Null
      $Socket.Receive( $NTPData ) | Out-Null
      $Seconds = [BitConverter]::ToUInt32( $NTPData[43..40], 0 )
            (Get-Date -Date '1/1/1900' ).AddSeconds( $Seconds ).ToLocalTime()
      Out-Verbose "Successfully received time from NTP $ComputerName"
    } catch {
      #get-date -date '1/1/1900'
      Out-Verbose "Failed receiving time from $ComputerName, server not up, or not running NTP"
      Write-Error -Message "Could not make an NTP connection over port $Port to $ComputerName"
    }
  }

  end {
    $ErrorActionPreference = $oldEA
    Out-Verbose $fxn "Complete."
  }
}