PS. It uses WinAPI to get UTC date, for linux that needs to be adapted
Here is alternative
viewtopic.php?t=81257
Code: Select all
EnableExplicit
;{ Simple NTP Client }
; 2017-2023 Luna Sole
; v 1.0.0.5
Structure ntp_packet Align #PB_Structure_AlignC
livnmode.a ; li - 2 bits, vn = 3 bits, mode = 3 bits
stratum.a ; Stratum level of the local clock
poll.a ; Maximum interval between successive messages
precision.a ; Precision of the local clock
rootDelay.l ; Total round trip delay time
rootDispersion.l ; Max error aloud from primary clock source
refId.l ; Reference clock identifier
refTm_s.l ; Reference time-stamp seconds
refTm_f.l ; Reference time-stamp fraction of a second
origTm_s.l ; Originate time-stamp seconds
origTm_f.l ; Originate time-stamp fraction of a second
rxTm_s.l ; Received time-stamp seconds
rxTm_f.l ; Received time-stamp fraction of a second
txTm_s.l ; Transmit time-stamp seconds
txTm_f.l ; Transmit time-stamp fraction of a second
EndStructure ; = 48 bytes
; Difference between UNIX time (used by PB, starts at 1970) and NTP time (starts at 1900) = 70 years
#NTP_TIMESTAMP_DELTA = 2208988800
; ------------------------------------------------ ;
; Inverts byte order (BE <> LE)
; RETURN: inverted long
Procedure.l BSwap32(L.l)
ProcedureReturn 255&L>>24|(255&L)<<24|(255&L>>16)<<8|(255&L>>8)<<16
EndProcedure
; Returns system time in UTC format
Procedure GetUTCTime()
Protected TINFO.SYSTEMTIME
GetSystemTime_(TINFO)
ProcedureReturn Date(TINFO\wYear, TINFO\wMonth, TINFO\wDay, TINFO\wHour, TINFO\wMinute, TINFO\wSecond)
EndProcedure
; Updates system time/date (UTC)
; The calling process must have the SE_SYSTEMTIME_NAME privilege. This privilege is disabled by default.
Procedure SetUTCTime(Date)
Protected TINFO.SYSTEMTIME
TINFO\wDay = Day(Date)
TINFO\wHour = Hour(Date)
TINFO\wMinute = Minute(Date)
TINFO\wMonth = Month(Date)
TINFO\wSecond = Second(Date)
TINFO\wYear = Year(Date)
SetSystemTime_(TINFO)
EndProcedure
; Here "NIST Internet Time Servers" may be used to get actual time
; ! Do not query them more often than once per 4 seconds
; See (http://tf.nist.gov/tf-cgi/servers.cgi) for details
;
; Performs request to specified NTP server and returns date
; Server$ an IP or hostname of time server
; UTC If True, the return will be UTC time, else localized time
; TimeOut value in seconds to wait for reply
; RETURN: date in UNIX format received from NTP server
; RETURN: negative value on error:
; -3: Connection failed
; -2: Timeout expired
; -1: Invalid response received
Procedure NTPDate(Server$, UTC, TimeOut = 30)
; Result
Protected NTPTime
Protected hServ = OpenNetworkConnection(Server$, 123, #PB_Network_UDP, TimeOut * 1000)
Protected nWait = Date() + TimeOut
; Perform request
If hServ
; Send NTP query
Protected nBuffer.ntp_packet
nBuffer\livnmode = %00011011 ; which means li = 0, vn = 3, and mode = 3
nBuffer\txTm_s = BSwap32(#NTP_TIMESTAMP_DELTA + GetUTCTime())
SendNetworkData(hServ, nBuffer, SizeOf(ntp_packet))
; Wait for response and process it
Repeat
If NetworkClientEvent(hServ) = #PB_NetworkEvent_Data
ClearStructure(nBuffer, ntp_packet)
If ReceiveNetworkData(hServ, @nBuffer, SizeOf(nBuffer)) = SizeOf(nBuffer)
; Convert required values from "big endian" to little
; Don't forget to convert anything else you need from response
nBuffer\txTm_s = BSwap32(nBuffer\txTm_s)
nBuffer\origTm_s = BSwap32(nBuffer\origTm_s)
nBuffer\rxTm_s = BSwap32(nBuffer\rxTm_s)
; Calculate resulting difference taking all that stuff into quads, cause unsigned ints needed
Protected.q a, b, c, d
CopyMemory(@nBuffer\rxTm_s, @a, 4)
CopyMemory(@nBuffer\origTm_s, @b, 4)
CopyMemory(@nBuffer\txTm_s, @c, 4)
d = #NTP_TIMESTAMP_DELTA + GetUTCTime()
; Calculate resulting time
If UTC
; Calculate result to UTC
NTPTime = GetUTCTime() + ((a - b) + (c - d)) / 2
Else
; Calculate comparing to local time
NTPTime = Date() + ((a - b) + (c - d)) / 2
EndIf
Else
; FAIL: Invalid response received
NTPTime = -1
EndIf
Break
Else
If Date() >= nWait
; FAIL: Timeout expired
NTPTime = -2
Break
EndIf
Delay(8)
EndIf
ForEver
CloseNetworkConnection(hServ)
Else
; FAIL: Connect failed
NTPTime = -3
EndIf
ProcedureReturn NTPTime
EndProcedure
;}
;------------------------------------------------------------------------
; Example
InitNetwork()
OpenConsole("Simple NTP client")
; Do all the stuff
Define NTPDate = NTPDate("time.nist.gov", #False, 30)
If NTPDate < 0
PrintN("Failed NTP query: " + Str(NTPDate))
Else
PrintN("System date: " + FormatDate("%yyyy.%mm.%dd", Date()))
PrintN("NTP server date: " + FormatDate("%yyyy.%mm.%dd", NTPDate))
PrintN("")
PrintN("System time: " + FormatDate("%hh:%ii:%ss", Date()))
PrintN("NTP server time: " + FormatDate("%hh:%ii:%ss", NTPDate))
EndIf
Input()