TheXman Posted October 28, 2019 Share Posted October 28, 2019 (edited) On 10/28/2019 at 5:20 AM, CYCho said: @TheXman After several hours of googling, I came up with the following code for calculating fractions of NTP time in millisecs. Your review and comment will be appreciated. $iMilliSecs = Int(Dec(Hex(BinaryMid($xResponse, 45, 4)), $NUMBER_64BIT)/2^32*1000) $iMilliSecs = StringFormat("%03i", $iMilliSecs) Very nice! It looks almost exactly like the solution that I came up with. The only difference between yours and mine is that I round the milliseconds. $iSeconds = Dec(Hex(BinaryMid($xResponse, 41, 4)), $NUMBER_64BIT) ; seconds since 1900-01-01 00:00:00 $iFraction = Dec(Hex(BinaryMid($xResponse, 45, 4)), $NUMBER_64BIT) ; picosec = 1 trillionth of a second (10^-12) $iMsecs = Round($iFraction / 2^32 * 1000) ; round to the nearest integer My full script is below: Spoiler expandcollapse popup#include <Constants.au3> #include <date.au3> ntp_example() Func ntp_example() Const $NTP_SERVER = "time.windows.com" Const $MY_TZ_OFFSET = -5 ; Timezone offset in hours ( Local $tBuffer Local $aSocket Local $xRequest = Binary(""), $xResponse = Binary("") Local $sTimestampLocal = "", $sTimestampUTC = "" Local $hTimeoutTimer Local $iSeconds = 0, $iFraction = 0, $iMillisecs = 0 ; Create the NTP request using a 48 byte buffer $tBuffer = DllStructCreate("byte[48]") DllStructSetData($tBuffer, 1, 0x23) ; 00 100 011 = LI(0) / VN(4-NTPv4) / Mode(3-Client) ; Copy the buffer to a variable for sending $xRequest = DllStructGetData($tBuffer, 1) write_log_line("DEBUG: Binary request = " & $xRequest) ; Send NTP request UDPStartup() If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "UDPStartup failed - @error = " & @error) OnAutoItExitRegister("udp_shutdown") $aSocket = UDPOpen(TCPNameToIP($NTP_SERVER), 123) If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "UDPOpen failed - @error = " & @error) UDPSend($aSocket, $xRequest) If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "UDPSend failed - @error = " & @error) ; Receive NTP response $hTimeoutTimer = TimerInit() Do If TimerDiff($hTimeoutTimer) > 2000 Then ExitLoop ; If no response within 2 seconds, then exit the loop $xResponse = UDPRecv($aSocket, DllStructGetSize($tBuffer), $UDP_DATA_BINARY) If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "UDPRecv failed - @error = " & @error) Until $xResponse <> Binary("") write_log_line("DEBUG: Binary response = " & Binary($xResponse)) ; Close the socket UDPCloseSocket($aSocket) ; If the request timed out, exit with a message If $xResponse = Binary("") Then Exit MsgBox($MB_ICONERROR, "ERROR", "UDPRecv timed out") ; Parse & display timestamp values ; - Current time is calculated from the xmit timestamp in NTP response header ; - Xmit timestamp seconds is a big-endian, uint32, at binary position 41 ; - Xmit timestamp fraction (picoseconds) is a big-endian, uint32, at binary position 45 $iSeconds = Dec(Hex(BinaryMid($xResponse, 41, 4)), $NUMBER_64BIT) ; seconds since 1900-01-01 00:00:00 $iFraction = Dec(Hex(BinaryMid($xResponse, 45, 4)), $NUMBER_64BIT) ; fractional portion $iMillisecs = Round($iFraction / 2^32 * 1000) ; round to nearest integer write_log_line() write_log_line(StringFormat("DEBUG: Xmit Timestamp Seconds = 0x%s (%s)", Hex(BinaryMid($xResponse, 41, 4)), $iSeconds)) write_log_line(StringFormat("DEBUG: Xmit Timestamp Fraction = 0x%s (%s picosecs) (%.12f decimal secs) (%i msecs)", _ Hex(BinaryMid($xResponse, 45, 4)), $iFraction, $iFraction / 2^32, $iMillisecs)) ; Display current UTC & Local time $sTimestampUTC = StringReplace(_DateAdd("s", $iSeconds, "1900/01/01 00:00:00"), "/", "-") & StringFormat(".%03i", $iMillisecs) $sTimestampLocal = StringReplace(_DateAdd("s", $iSeconds + (3600 * $MY_TZ_OFFSET), "1900/01/01 00:00:00"), "/", "-") & StringFormat(".%03i", $iMillisecs) write_log_line() write_log_line("Date/Time (UTC) = " & $sTimestampUTC) write_log_line("Date/Time (Local) = " & $sTimestampLocal) EndFunc Func udp_shutdown() UDPShutdown() EndFunc Func write_log_line($sMessage = "") Local $sNow = StringReplace(_NowCalc(), "/", "-") ConsoleWrite($sNow & ": " & $sMessage & @CRLF) EndFunc Edited October 30, 2019 by TheXman CYCho 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
CYCho Posted October 28, 2019 Author Share Posted October 28, 2019 @TheXman Thank you. I am glad that I did it. The last 2 days were an intensive course of learning for me and I enjoyed it. I appreciate your help. TheXman 1 zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
TheXman Posted October 28, 2019 Share Posted October 28, 2019 6 minutes ago, CYCho said: @TheXman Thank you. I am glad that I did it. The last 2 days were an intensive course of learning for me and I enjoyed it. I appreciate your help. You're welcome! Feel free to reach out to me directly if you ever run into any AutoIt obstacles in the future. CYCho 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
CYCho Posted October 29, 2019 Author Share Posted October 29, 2019 (edited) Using @TheXman's UDF to get time from NTP server, I completely revamped my original code as below. I don't know the real benefit of doing it, but the code now synchronizes computer time to millisec level. According to my experience, Google time server produced far less timed out errors than other servers. I didn't have to worry about timezone offset because Windows takes care of it. expandcollapse popup;~ Many thanks to @TheXman for his kind guidance. ;~ https://www.autoitscript.com/forum/topic/200643-pulling-time-from-ntp-server/?do=findComment&comment=1439629 #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #AutoIt3Wrapper_Outfile=NTP_Time_V4.exe #AutoIt3Wrapper_Res_Fileversion=4.0 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #RequireAdmin #include <Constants.au3> #include <Date.au3> Global $hTimeoutTimer = TimerInit() While 1 If Ping("www.google.com") > 0 Then ExitLoop If TimerDiff($hTimeoutTimer) > 120000 Then WriteLog(0, "System has no internet connection") Exit EndIf Sleep(50) WEnd Global $NTP_Server = 'time.google.com', $NTP_Time NTP_GetTime() System_SetTime() Func System_SetTime() ; 2019/10/28 23:09:52.522 ; 12345678901234567890123 Local $m = StringMid($NTP_Time, 6, 2) Local $d = StringMid($NTP_Time, 9, 2) Local $y = StringMid($NTP_Time, 1, 4) Local $h = StringMid($NTP_Time, 12, 2) Local $mi = StringMid($NTP_Time, 15, 2) Local $s = StringMid($NTP_Time, 18, 2) Local $ms = StringMid($NTP_Time, 21, 3) ;~ Sets the new current time to the computer Local $tCurr = _Date_Time_EncodeSystemTime($m, $d, $y, $h, $mi, $s, $ms) Local $tTime = _Date_Time_GetSystemTime() _Date_Time_SetSystemTime(DllStructGetPtr($tCurr)) Local $aTime = _Date_Time_SystemTimeToArray($tTime) WriteLog($aTime, "Update Time: " & $NTP_Time & " UTC") EndFunc ;==>System_SetTime Func NTP_GetTime() Local $tBuffer Local $aSocket Local $xRequest = Binary(""), $xResponse = Binary(""), $hTimeoutTimer, $hEchoTimer, $iDelay Local $iSeconds= 0, $iFractions = 0, $iMsecs = 0 ; Create the NTP request using a 48 byte buffer $tBuffer = DllStructCreate("byte[48]") DllStructSetData($tBuffer, 1, 0x23) ; 00 100 011 = LI(0) / VN(4-NTPv4) / Mode(3-Client) ; Copy the buffer to a variable for sending $xRequest = DllStructGetData($tBuffer, 1) ; Send NTP request UDPStartup() If @error Then WriteLog(0, "UDPStartup failed - @error = " & @error) Exit EndIf OnAutoItExitRegister("udp_shutdown") $aSocket = UDPOpen(TCPNameToIP($NTP_Server), 123) If @error Then WriteLog(0, "UDPOpen failed - @error = " & @error) Exit EndIf Sleep(50) $hTimeoutTimer = TimerInit() While 1 $hEchoTimer = TimerInit() UDPSend($aSocket, $xRequest) If @error Then WriteLog(0, "UDPSend failed - @error = " & @error) Exit EndIf Do $xResponse = UDPRecv($aSocket, DllStructGetSize($tBuffer), $UDP_DATA_BINARY) If @error Then WriteLog(0, "UDPRecv failed - @error = " & @error) Exit EndIf Until $xResponse <> Binary("") $iDelay = Round(TimerDiff($hEchoTimer)/2) If $iDelay < 100 Then ExitLoop EndIf If TimerDiff($hTimeoutTimer) > 120000 Then ; If no response within 2 seconds, then exit WriteLog(0, "UDPRecv timed out") Exit EndIf Sleep(100) WEnd ; Close the socket UDPCloseSocket($aSocket) ; Parse timestamp values ; - Current time is calculated from the xmit timestamp in NTP response header ; - Xmit timestamp seconds is a big-endian, uint32, at binary position 41 ; - Xmit timestamp fraction is a big-endian, uint32, at binary position 45 $iSeconds = Dec(Hex(BinaryMid($xResponse, 41, 4)), $NUMBER_64BIT) ; seconds since 1900-01-01 00:00:00 $iFractions = Dec(Hex(BinaryMid($xResponse, 45, 4)), $NUMBER_64BIT) ; the maximum value is 0xFFFFFFFF, which represents 1 second $iMsecs = Round($iFractions / 2^32 * 1000) + $iDelay ; It normally takes about 50 milsecs to get NTP time If $iMsecs >= 1000 Then $iSeconds += 1 $iMsecs -= 1000 EndIf ; Current NTP time $NTP_Time = _DateAdd("s", $iSeconds, "1900/01/01 00:00:00") & StringFormat(".%03i", $iMsecs) EndFunc ;==>NTP_GetTime Func udp_shutdown() UDPShutdown() EndFunc ;==>udp_shutdown Func WriteLog($pTime, $sMessage) Local $fn, $sTime If $pTime = 0 Then $fn = FileOpen(@ScriptDir & "\TimeSync Failed.log", 2) $sTime = _NowCalc() Else $fn = FileOpen(@ScriptDir & "\TimeSync.log", 2) FileDelete(@ScriptDir & "\TimeSync Failed.log") $sTime = StringFormat("System Time: %04d/%02d/%02d %02d:%02d:%02d.%03d UTC", $pTime[2], $pTime[0], $pTime[1], $pTime[3], $pTime[4], $pTime[5], $pTime[6]) EndIf FileWrite($fn, $sTime & @CRLF & $sMessage) FileClose($fn) EndFunc ;==>WriteLog Edited November 24, 2019 by CYCho zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
TheXman Posted October 29, 2019 Share Posted October 29, 2019 (edited) All of the variables that you have defined that are not inside of a function are global in scope, even if you define them as Local. So all of the Local vars at the top of your script should actually be defined as Global. Change your au3 parameters to the following and you will see the warnings: #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d Edited October 29, 2019 by TheXman CYCho 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
CYCho Posted October 29, 2019 Author Share Posted October 29, 2019 (edited) @TheXman, Thank you. I changed it. Edited October 29, 2019 by CYCho zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
CYCho Posted October 31, 2019 Author Share Posted October 31, 2019 The maximum value of NTP timestamp fraction is 0xFFFFFFFF, which represents 1 second. So 1 fraction is approximately 232 picoseconds. zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
CYCho Posted November 4, 2019 Author Share Posted November 4, 2019 (edited) The compiled version of this code(NTP_Time_V4.exe attached to the 1st post of this topic) was cleared by Microsoft Windows Defender from false detection as of Definition 1.305.2722.0. I attached the file to the first post of this topic. Edited November 24, 2019 by CYCho zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
mLipok Posted December 6, 2019 Share Posted December 6, 2019 Did you look here: ? Signature beginning:* Please remember: "AutoIt"..... * Wondering who uses AutoIt and what it can be used for ? * Forum Rules ** ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Code * for other useful stuff click the following button: Spoiler Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API * ErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 * My contribution to others projects or UDF based on others projects: * _sql.au3 UDF * POP3.au3 UDF * RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF * SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane * Useful links: * Forum Rules * Forum etiquette * Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * Wiki: * Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX IE Related: * How to use IE.au3 UDF with AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskScheduler * IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related: * How to get reference to PDF object embeded in IE * IE on Windows 11 * I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions * EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *I also encourage you to check awesome @trancexx code: * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuff * OnHungApp handler * Avoid "AutoIt Error" message box in unknown errors * HTML editor * winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/ "Homo sum; humani nil a me alienum puto" - Publius Terentius Afer"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming" , be and \\//_. Anticipating Errors : "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty." Signature last update: 2023-04-24 Link to comment Share on other sites More sharing options...
CYCho Posted December 6, 2019 Author Share Posted December 6, 2019 @mLipok Thank you for your reference. I will take a look. Whatever it is, I know I will have to struggle with it for some time to understand it. It will be a fun to learn new things. zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
CYCho Posted December 6, 2019 Author Share Posted December 6, 2019 (edited) @mLipok I compared the performance of 2 different approaches to get NTP server time. Approach #1: expandcollapse popup#include <Date.au3> #include <StructureConstants.au3> #include <WinAPIMisc.au3> $tFT = _NTP_FT('pool.ntp.org') For $i = 1 To 10 $hTimer = TimerInit() $tFT = _NTP_FT('pool.ntp.org') ConsoleWrite(_Date_Time_FileTimeToStr($tFT) & " - " & TimerDiff($hTimer) & @CRLF) Next Func _NTP_FT($sServer, $fLocal = True) Local $tNTP = DllStructCreate('byte Header[4];byte RootDelay[4];byte RootDispersion[4];byte ReferenceIdentifier[4];byte ReferenceTimestamp[8];byte OriginateTimestamp[8];byte ReceiveTimestamp[8];byte TransmitTimestamp[8];byte KeyIdentifier[4];byte MessageDigest[16]') Local $tPacket = DllStructCreate('byte Packet[68]', DllStructGetPtr($tNTP)) Local $bPacket = 0, $tFT, $tQW, $aSocket, $aResult ;~ 0x1B000000 = 00011011 00000000 00000000 00000000b (LI = 00b VN = 011b Mode = 011b Stratum = 00000000b Poll = 00000000b Precision = 00000000b) $tNTP.Header = Binary('0x1B000000') UDPStartup() If @error Then Return SetError(1, 0, 0) EndIf $aSocket = UDPOpen(TCPNameToIP($sServer), 123) If @error Then ; Nothing Else UDPSend($aSocket, $tPacket.Packet) If @error Then ; Nothing Else While 1 $bPacket = UDPRecv($aSocket, 68, 1) If (@error) Or ($bPacket) Then ExitLoop EndIf Sleep(100) WEnd EndIf EndIf UDPCloseSocket($aSocket) UDPShutdown() If Not $bPacket Then Return SetError(2, 0, 0) EndIf $tFT = DllStructCreate($tagFILETIME) If $fLocal Then $tQW = DllStructCreate('uint64 Timestamp') Else $tQW = DllStructCreate('uint64 Timestamp', DllStructGetPtr($tFT)) EndIf $tPacket.Packet = $bPacket $tQW.Timestamp = _WinAPI_SwapDWord(DllStructGetData(DllStructCreate('uint', DllStructGetPtr($tNTP, 'TransmitTimestamp')), 1)) * 10000000 + 94354848000000000 If $fLocal Then $aResult = DllCall('kernel32.dll', 'bool', 'FileTimeToLocalFileTime', 'struct*', $tQW, "struct*", $tFT) If (@error) Or (Not $aResult[0]) Then Return SetError(3, 0, 0) EndIf EndIf Return SetError(0, 0, $tFT) EndFunc ;==>_NTP_FT The reault: 12/06/2019 22:29:06 - 50.5885 12/06/2019 22:29:06 - 48.0765 12/06/2019 22:29:06 - 52.2912 12/06/2019 22:29:06 - 46.8422 12/06/2019 22:29:06 - 42.2072 12/06/2019 22:29:07 - 44.1788 12/06/2019 22:29:07 - 43.5889 12/06/2019 22:29:07 - 42.9144 12/06/2019 22:29:07 - 45.8183 Approach #2 expandcollapse popup#include <Constants.au3> #include <Date.au3> Global $NTP_Server = 'pool.ntp.org', $NTP_Time NTP_GetTime() For $i = 1 To 10 $tTimer = TimerInit() NTP_GetTime() ConsoleWrite($NTP_Time & " - " & TimerDiff($tTimer) & @CRLF) Next Func NTP_GetTime() Local $tBuffer Local $aSocket Local $xRequest = Binary(""), $xResponse = Binary(""), $hTimeoutTimer, $hEchoTimer Local $iSeconds= 0, $iFractions = 0, $iMsecs = 0 ; Create the NTP request using a 48 byte buffer $tBuffer = DllStructCreate("byte[48]") DllStructSetData($tBuffer, 1, 0x23) ; 00 100 011 = LI(0) / VN(4-NTPv4) / Mode(3-Client) ; Copy the buffer to a variable for sending $xRequest = DllStructGetData($tBuffer, 1) ; Send NTP request UDPStartup() If @error Then ConsoleWrite("UDPStartup failed - @error = " & @error) Exit EndIf OnAutoItExitRegister("udp_shutdown") $aSocket = UDPOpen(TCPNameToIP($NTP_Server), 123) If @error Then ConsoleWrite("UDPOpen failed - @error = " & @error) Exit EndIf $hEchoTimer = TimerInit() UDPSend($aSocket, $xRequest) If @error Then ConsoleWrite("UDPSend failed - @error = " & @error) Exit EndIf Do $xResponse = UDPRecv($aSocket, DllStructGetSize($tBuffer), $UDP_DATA_BINARY) If @error Then ConsoleWrite("UDPRecv failed - @error = " & @error) Exit EndIf Until $xResponse <> Binary("") $iDelay = TimerDiff($hEchoTimer) ; Close the socket UDPCloseSocket($aSocket) ; Parse timestamp values ; - Current time is calculated from the xmit timestamp in NTP response header ; - Xmit timestamp seconds is a big-endian, uint32, at binary position 41 ; - Xmit timestamp fraction is a big-endian, uint32, at binary position 45 $iSeconds = Dec(Hex(BinaryMid($xResponse, 41, 4)), $NUMBER_64BIT) ; seconds since 1900-01-01 00:00:00 $iFractions = Dec(Hex(BinaryMid($xResponse, 45, 4)), $NUMBER_64BIT) ; the maximum value is 0xFFFFFFFF, which represents 1 second $iMsecs = Round($iFractions / 2^32 * 1000) + Round($iDelay/2) If $iMsecs >= 1000 Then $iSeconds += 1 $iMsecs -= 1000 EndIf ; Current NTP time $NTP_Time = _DateAdd("s", $iSeconds, "1900/01/01 00:00:00") $NTP_Time = _DateAdd("h", 9, $NTP_Time) & StringFormat(".%03i", $iMsecs) EndFunc ;==>NTP_GetTime Func udp_shutdown() UDPShutdown() EndFunc ;==>udp_shutdown The result: 2019/12/06 22:51:24.255 - 5.5304 2019/12/06 22:51:24.260 - 4.3448 2019/12/06 22:51:24.264 - 3.9764 2019/12/06 22:51:24.268 - 4.0598 2019/12/06 22:51:24.272 - 3.9179 2019/12/06 22:51:24.277 - 5.038 2019/12/06 22:51:24.281 - 5.3846 2019/12/06 22:51:24.287 - 4.7938 2019/12/06 22:51:24.293 - 6.4303 2019/12/06 22:51:24.298 - 5.383 I don't understand what makes this large difference in terms of time taken for each iteration. For unknow reason, the frst iteration always produced an outlying result, so I left that out. Edited December 6, 2019 by CYCho zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
CYCho Posted December 18, 2019 Author Share Posted December 18, 2019 (edited) In connection with this topic a need arose to compare two time strings in milliseconds. As _DateDiff function does not support millisecond data type, I came up with a UDF based on the original _DateDiff function. expandcollapse popup#include <Date.au3> $sDate1 = "2019/12/19 23:16:24" $sDate2 = "2019/12/20 23:16:24.02" ConsoleWrite("Difference in seconds: " & _DateDiffEx("s", $sDate1, $sDate2) & @CRLF) ConsoleWrite("Difference in milliseconds: " & _DateDiffEx("ms", $sDate1, $sDate2) & @CRLF) Func _DateDiffEx($sType, $sStartDate, $sEndDate) Local $iDiff If $sType = "ms" Or $sType = "s" Then Local $sStartMS, $sEndMS, $iDiffSec If StringInStr($sStartDate, ".") Then $sStartMS = StringMid($sStartDate, StringInStr($sStartDate, "."), 5)*1000 $sStartDate = StringLeft($sStartDate, StringInStr($sStartDate, ".")-1) EndIf If StringInStr($sEndDate, ".") Then $sEndMS = StringMid($sEndDate, StringInStr($sEndDate, "."), 5)*1000 $sEndDate = StringLeft($sEndDate, StringInStr($sEndDate, ".")-1) EndIf $iDiffSec = _DateDiff("s", $sStartDate, $sEndDate) If @error Then Return SetError(@error, 0, 0) $iDiff = $iDiffSec*1000+Round($sEndMS-$sStartMS) If $sType = "s" Then $iDiff = StringFormat("%.3f", $iDiff/1000) EndIf Else If StringInStr($sStartDate, ".") Then $sStartDate = StringLeft($sStartDate, StringInStr($sStartDate, ".")-1) EndIf If StringInStr($sEndDate, ".") Then $sEndDate = StringLeft($sEndDate, StringInStr($sEndDate, ".")-1) EndIf $iDiff = _DateDiff($sType, $sStartDate, $sEndDate) EndIf Return SetError(@error, 0, $iDiff) EndFunc Edited December 30, 2019 by CYCho zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
CYCho Posted March 17, 2020 Author Share Posted March 17, 2020 (edited) With this code running in my desktop, I found that my computer needed an average upward adjustment of 1.8 seconds a day. Even though I can schedule this code to run as often as possible to forcefully adjust the system time at short intervals, I was wondering if there was a way to let the system clock run a little bit faster to keep better time by itself. And I found _Date_Time_SetSystemTimeAdjustment() function and included the following lines at the end of the code. The result is very satisfactory: it now lags less than a quarter of a second a day. $aInfo = _Date_Time_GetSystemTimeAdjustment() $iAdjustment = $aInfo[1] + 3 ; 156250 + 3 : The increment of 1 in $iAdjustment value represents 0.55296 second a day. _Date_Time_SetSystemTimeAdjustment($iAdjustment, False) Edited March 17, 2020 by CYCho zPlayer - A Small Audio and Video Player Time Sync + SystemTimeAdjustment Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now