Source Code of jQuery plugin at https://github.com/JohnRDOrazio/jQuery-Clock-Plugin >> Source Code of this example <<
Server: | 0.uk.pool.ntp.org |
VN (version number): | 3 |
Mode: | 4 |
Stratum: | 2 |
Origin time: | 1732184496.6822 |
Remote NTP Server Received: | 1732184496.6816 |
Remote NTP Server Transmitted: | 1732184496.6816 |
Delay: | 2 ms |
NTP time: | 1732184496 |
NTP time formatted: | 2024-11-21 10:21:36 AM UTC .6799 |
NTP time formatted to Australia/Sydney timezone: | 2024-11-21 09:21:36 PM Australia/Sydney |
NTP time compensated with timezone offset: | 1732224096 |
NTP time compensated with timezone offset and formatted with Australia/Sydney timezone: | 2024-11-22 08:21:36 AM Australia/Sydney |
<?php /* Query an NTP time server on port 123 (SNTP protocol) : */ $bit_max = 4294967296; $epoch_convert = 2208988800; $vn = 3; $servers = array('0.uk.pool.ntp.org','1.uk.pool.ntp.org','2.uk.pool.ntp.org','3.uk.pool.ntp.org'); $server_count = count($servers); //see rfc5905, page 20 //first byte //LI (leap indicator), a 2-bit integer. 00 for 'no warning' $header = '00'; //VN (version number), a 3-bit integer. 011 for version 3 $header .= sprintf('%03d',decbin($vn)); //Mode (association mode), a 3-bit integer. 011 for 'client' $header .= '011'; //echo bindec($header); //construct the packet header, byte 1 $request_packet = chr(bindec($header)); //we'll use a for loop to try additional servers should one fail to respond $i = 0; for($i; $i < $server_count; $i++) { $socket = @fsockopen('udp://'.$servers[$i], 123, $err_no, $err_str,1); if ($socket) { //add nulls to position 11 (the transmit timestamp, later to be returned as originate) //10 lots of 32 bits for ($j=1; $j<40; $j++) { $request_packet .= chr(0x0); } //the time our packet is sent from our server (returns a string in the form 'msec sec') $local_sent_explode = explode(' ',microtime()); $local_sent = $local_sent_explode[1] + $local_sent_explode[0]; //add 70 years to convert unix to ntp epoch $originate_seconds = $local_sent_explode[1] + $epoch_convert; //convert the float given by microtime to a fraction of 32 bits $originate_fractional = round($local_sent_explode[0] * $bit_max); //pad fractional seconds to 32-bit length $originate_fractional = sprintf('%010d',$originate_fractional); //pack to big endian binary string $packed_seconds = pack('N', $originate_seconds); $packed_fractional = pack("N", $originate_fractional); //add the packed transmit timestamp $request_packet .= $packed_seconds; $request_packet .= $packed_fractional; if (fwrite($socket, $request_packet)) { $data = NULL; stream_set_timeout($socket, 1); $response = fread($socket, 48); //the time the response was received $local_received = microtime(true); //echo 'response was: '.strlen($response).$response; } fclose($socket); if (strlen($response) == 48) { //the response was of the right length, assume it's valid and break out of the loop break; } else { if ($i == $server_count-1) { //this was the last server on the list, so give up die('unable to establish a connection'); } } } else { if ($i == $server_count-1) { //this was the last server on the list, so give up die('unable to establish a connection'); } } } //unpack the response to unsigned long for calculations $unpack0 = unpack("N12", $response); //print_r($unpack0); //present as a decimal number $remote_originate_seconds = sprintf('%u', $unpack0[7])-$epoch_convert; $remote_received_seconds = sprintf('%u', $unpack0[9])-$epoch_convert; $remote_transmitted_seconds = sprintf('%u', $unpack0[11])-$epoch_convert; $remote_originate_fraction = sprintf('%u', $unpack0[8]) / $bit_max; $remote_received_fraction = sprintf('%u', $unpack0[10]) / $bit_max; $remote_transmitted_fraction = sprintf('%u', $unpack0[12]) / $bit_max; $remote_originate = $remote_originate_seconds + $remote_originate_fraction; $remote_received = $remote_received_seconds + $remote_received_fraction; $remote_transmitted = $remote_transmitted_seconds + $remote_transmitted_fraction; //unpack to ascii characters for the header response $unpack1 = unpack("C12", $response); //print_r($unpack1); //echo 'byte 1: ' . $unpack1[1] . ' | '; //the header response in binary (base 2) $header_response = base_convert($unpack1[1], 10, 2); //pad with zeros to 1 byte (8 bits) $header_response = sprintf('%08d',$header_response); //Mode (the last 3 bits of the first byte), converting to decimal for humans; $mode_response = bindec(substr($header_response, -3)); //VN $vn_response = bindec(substr($header_response, -6, 3)); //the header stratum response in binary (base 2) $stratum_response = base_convert($unpack1[2], 10, 2); $stratum_response = bindec($stratum_response); //echo 'stratum: ' . bindec($stratum_response); //calculations assume a symmetrical delay, fixed point would give more accuracy $delay = (($local_received - $local_sent) / 2) - ($remote_transmitted - $remote_received); $delay_ms = round($delay * 1000) . ' ms'; //echo 'delay: ' . $delay * 1000 . 'ms'; $server = $servers[$i]; $ntp_time = $remote_transmitted - $delay; [ $time, $microseconds ] = explode( '.', $ntp_time ); $ntp_time_formatted = implode('.', [ date('Y-m-d H:i:s A e ', $time), $microseconds ]); date_default_timezone_set('Australia/Sydney'); $timezone = ""; if (date_default_timezone_get()) { $timezone = date_default_timezone_get(); } elseif(ini_get('date.timezone')){ $timezone = ini_get('date.timezone'); } $time_formatted = date('Y-m-d h:i:s A e', $time); $time_adjusted = $time + date('Z'); $time_adjusted_formatted = date('Y-m-d h:i:s A e', $time_adjusted); $isDST = date('I', $time); ?>
<html> <head> <title>jQuery Clock NTP timestamp example</title> <meta charset="UTF-8"> <style type="text/css"> html, body {height: 100%; margin: 0; padding: 0; background-color: Gray; } #clocks-container { border: 1px groove White; border-radius: 15px; padding: 10px; width: 40%; float: left; margin: 30px; background-color: LightGray; text-align: center; } #table-container { border: 1px solid Green; border-radius: 15px; padding: 10px; width: 40%; float: left; margin: 30px; background-color: White; text-align: center; } #ntp-results-table { } td { width: 160px; height: 20px; padding: 4px; border: 1px solid #000; font-size: 12px; } .ntp_response { width: 240px; } /* SAMPLE CSS STYLES FOR JQUERY CLOCK PLUGIN */ .jqclock { text-align:center; border: 2px #369 ridge; background-color: #69B; padding: 10px; margin:20px auto; width: 40%; box-shadow: 5px 5px 15px #005; } .jqclock > .clockdate { color: DarkRed; font-weight: bold; background-color: #8BD; margin-bottom: 10px; font-size: 18px; display: block; padding: 5px 0; text-shadow: 1px 1px 3px #FCC; outline: 1px solid White; } .jqclock > .clocktime { border: 2px inset DarkBlue; outline: 3px ridge LightBlue; background-color: #444; padding: 5px 0; font-size: 14px; font-family: "Courier"; color: LightGreen; margin: 2px; display: block; font-weight:bold; text-shadow: 1px 1px 1px Black; } .servertimetest { border: 1px solid Blue; margin: 2px; } </style> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script type="text/javascript" src="//rawgit.com/JohnRDOrazio/jQuery-Clock-Plugin/master/jqClock.js"></script> <script type="text/javascript"> $(document).ready(function(){ const customtimestamp = parseInt( $("#jqclock").data("time") ); const isDST = Boolean( parseInt( $("#jqclock").data("dst") ) ); const timezone = $("#jqclock").data("timezone"); $("#jqclock").clock({ locale: "en", timestamp: customtimestamp, timezone: timezone, timeFormat: "h:i:s A T I", isDST: isDST, rate: 50 }); $("#jqclock-local").clock({"locale":"en"}); }); </script> </head> <body> <h1>jQuery Clock Server Example</h1> <p><i>Source Code of jQuery plugin at <a href="https://github.com/JohnRDOrazio/jQuery-Clock-Plugin">https://github.com/JohnRDOrazio/jQuery-Clock-Plugin</a></i></p> <div> <div id="table-container"> <h2>NTP Server Request</h2> <table id="ntp-results-table" border="0" align="center"> <tr> <td>Server: <td class="ntp_response"><?php echo $server;?></td> </tr> <tr> <td>VN (version number):</td> <td class="ntp_response"><?php echo $vn_response;?></td> </tr> <tr> <td>Mode:</td> <td class="ntp_response"><?php echo $mode_response;?></td> </tr> <tr> <td>Stratum:</td> <td class="ntp_response"><?php echo $stratum_response;?></td> </tr> <tr> <td>Origin time:</td> <td class="ntp_response"><?php echo $remote_originate;?></td> </tr> <tr> <td>Received:</td> <td class="ntp_response"><?php echo $remote_received;?></td> </tr> <tr> <td>Transmitted:</td> <td class="ntp_response"><?php echo $remote_transmitted;?></td> </tr> <tr> <td>Delay:</td> <td class="ntp_response"><?php echo $delay_ms;?></td> </tr> <tr> <td>NTP time:</td> <td class="ntp_response"><?php echo $ntp_timestamp;?></td> </tr> <tr> <td>NTP time formatted:</td> <td class="ntp_response"><?php echo $ntp_time_formatted;?></td> </tr> <tr> <td>NTP time formatted to Australia/Sydney timezone:</td> <td class="ntp_response"><?php echo $time_formatted; ?></td> </tr> <tr> <td>NTP time adjusted to Australia/Sydney timezone then adjusted to account for timezone offset:</td> <td class="ntp_response"><?php echo $time_adjusted;?></td> </tr> <tr> <td>NTP time adjusted to Europe/Rome timezone then adjusted to account for timezone offset, formatted:</td> <td class="ntp_response"><?php echo $time_adjusted_formatted; ?></td> </tr> </table> </div> <div id="clocks-container"> <h2>Current NTP Time:</h2> <div id="jqclock" data-time="<?php echo $time_adjusted; ?>" data-dst="<?php echo $isDST; ?>" data-timezone="<?php echo $timezone; ?>"></div> <div id="jqclock-reference-date"><?php echo strftime("%A, %B %e, %Y",$time); ?></div> <div class="servertimetest" id="jqclock-reference-time"><i>Time being fed into the jquery clock:</i> <br><?php echo $time_formatted; /* strftime("%I:%M:%S %p %Z",$time); */ ?></div> <h2>Compared to Current Local Time:</h2> <div id="jqclock-local"></div> </div> </div> </body> </html>