No announcement yet.


  • Filter
  • Time
  • Show
Clear All
new posts


    NIST-Time is an implementation of Mike Doty's code with suggestions by Clay Clear and Bob Scot since the original code. Many thanks to Mike. This version is without sound and simply reports via a message box, by default. I've concentrated on the time collection aspect since I live some distance from the time servers used.

    The NIST servers advance the time by 50 millisecnds to "partially compensate for network delays". Personally, I feel this is slightly higher than needed for US citizens and not enough for the rest of us. This compensation has been removed and replaced by an estimate of the return trip time or latency. For example, the latency for me in West London, England and Boulder, Colorado is about 75ms. For San José, California it is more like 95ms. Tests have shown that this latency approach works quite well.

    The NIST servers used are those listed here and put into TimeServers.dat. They are first randomly shuffled before trying them in turn. I've scheduled NIST-Time to execute every 12 hours so, with 17 servers, and assuming a success on the first try then, on average, they are being queried more than a week apart.

    The output takes the following form:

    The first line tells us the name of the first server to successfully give the time and the number in square brackets tells us how many servers were actually queried, including the success. The next line shows the full time stamp applied to our system and the following line tells us the correction that was applied. The next line tells us the latency estimate used.

    A typical line in TimeServers.dat takes the form:

    "","Columbia County, Georgia",0

    The third item is the numbers of failed queries. This is a recent addition to the code which I've been using for a few years now so I don't have any long term stats yet, although three servers are starting to stand out with the rest still on zero. If this persists then I may drop those three and just use 14 - still a good number. Obviously, these figures can be reset via a text editor but an easier way is to run the application manually via a command line using the switch /reset. In this case the time element of the application is bypassed, only the resetting is executed. As with other switches this is not space or case sensitive.

    The last thing we want on scheduling is an output. This can be suppressed with the switch /silent.

    I have put a shortcut to NIST-Time in my StartUp folder so that my clock is corrected at boot time - handy if I'm away for a few days with the PC switched off. However, this would not be handy for those with dial-up so another switch is available for them. Three options should help here: /Wait:10, /Wait:15 and /Wait:20. These will suspend querying a server for 10, 15 or 20 minutes after the application starts - choose whichever is best. If you tend to go on-line fairly quickly after booting then '/Silent /Wait:10' should do just fine. If going on-line is usually after 20 minutes from booting then don't put NIST-Time in the StartUp folder.

    There is no installation - I'm using C:\Program Files\NIST-Time\NIST-Time.exe and, of course, TimeServers.dat in the same folder.

    Both files are in the following zip:

    Added: Every now and then a leap second will either be added or subtracted at the end of the month. I knew a leap second would be added at the end of this month but I thought I was misreading the data because the message box should be telling us such. Some of the servers are now telling us that a leap second will be added this month. They are a bit late - it is Dec 6 in the UK. Fortunately, their time keeping is very much better.

    I forgot to mention that the code also considers the servers' healthy flag - if they are not in rude health at the time of the query then we move onto the next server.
    Last edited by David Roberts; 6 Dec 2008, 05:34 AM.

    A friend contacted me and said that NIST-Time wasn't working properly. Nothing ever does with this guy. It turned out that he used /Wait:5 but it didn't wait. I told him that was not one of the options. He pointed out that 10, 15 20 worked so why doesn't 5? It took a while for him to understand that /Wait:5, for example, was one name of three and they could have been anything - the app does not look at the 5, for example.

    He did have a point though.

    So, we now have /Wait:n where n>=1.

    I've taken the opportunity to add an icon rather than have the generic file icon - it is just an hour glass.

    I've also added a version sheet and made sure that Mike Doty is mentioned in the credits.

    The new version is at the same link above.

    I'd be interested if anyone has given this a try who lives further away from the servers than I do - just to see if the latency calculation is as well behaved as it is for me in the UK.


      I'd be interested if anyone has given this a try who lives further away from the servers than I do - just to see if the latency calculation is as well behaved as it is for me in the UK.
      Does this help? (From 'Down-under')..
      Attached Files
      Rgds, Dave


        Blimey! Spot on, bearing in mind I'm interested in the return trip only. Thanks, Dave.


          Two more switches.


          This simply creates/appends Correction.dat with the latest correction details and the entries take the form

          -138ms 28 Dec 08 18:00:01

          For those of you with pre Windows NT 3.5 this will be of only academic interest, if of any interest.


          /NoteCorrection comes into its own here but only wih Windows NT 3.5 or later, including therefore Win 2000, Win Xp and Win Vista and the various server incarnations.

          If we schedule NIST-Time at every six hours, say, then we may see a pattern of corrections indicating a drift. In my case, my clock was fast by about 1300ms per six hours.

          /AdjustClock: expects a value of 'n' to be the estimated millisecond correction over 24 hours.

          In my case then, I used /AdjustClock:-5200.

          The default behaviour with XP is that the clock is incremented by the interval between interrupts. The interval varies and Paul Dixon shows here that for every 8 interrupts 5 come in at 16ms and three come in at 15ms giving an average of 15.625ms ie a frequency of 64Hz. From MSDN: "The system is free to periodically refresh the time-of-day clock using other techniques." My understanding is that "other techniques" is to refer to the Real Time Clock and if a drift of more than one minute has occurred then the time-of-day is 'corrected' accordingly. This mode is called time-adjustment - disabled.

          Alternatively, with time-adjustment - enabled, the clock is incremented by a fixed amount and there is no system refresh. The default for this 'fixed amount' is, not surprisingly, 15.625ms. In this mode we should introduce our own reference and this may be achieved by getting the time from a time server and using that to refresh the clock.

          So far there is little difference between the two modes and they will coincide every 8 interrupts. However, in the second case we can alter the 'fixed amount' and in steps of 100 x nanoseconds. The default, dwTimeAdjustment, is then 156250.

          With a drift of -5200ms we get -9.404 x 100 x nanoseconds per interrupt, ROUNDed to -9, and dwTimeAdjustment is set to 156241.

          With ROUNDing it follows that our adjustment will be within 50 nanoseconds which translates to 276.48ms per day. With ABS(n) < 276.48 the adjustment will be zero so it would be a pointless exercise.

          Tests have shown that the drift has been reduced to -80ms per six hours ie -320ms per day. This is by no means an exact science and 320 may be regarded as close to 276.48. If we used 156240 then we may get 552.96 [ from 276.48x2] - 320 ie 232.96. However, I shall stay with the algorithm as is - -80 is a heck of a lot better than -1300.

          The time-adjustment - enabled mode does not persist between Windows sessions. The obvious place to execute it is within NIST-Time and ONLY on its first run. This can, of course, be implemented when NIST-Time is placed in the StartUp folder.

          My command line for NIST-Time in the StartUp folder is /Silent /AdjustClock:-5200.

          It is VERY important that /AdjustClock: is NOT used when NIST-Time is scheduled otherwise the adjustment will be applied to the last adjustment and so on - not good.

          If you find that your clock is much bettered behaved, as in accuracy, and you do not leave your machine on for days then you may be able to dispense with any scheduling and just settle for a clock adjustment and a refresh from a time server at boot up.

          I should mention that NIST-Time has been given system-time privilege to implement the adjustment - the privilege is disabled by default. This privilege is actually required to set the system time but it is enabled for us when the API SetSystemTime is executed. We should disable the privilege after the adjustment but I don't bother because it is local to NIST-Time which closes fairly quickly after. The function employed to set the privilege is by Scott Turchin here plus a bit of error checking on the API return values. Thanks Scott.

          Don't forget that minus sign in AdjustClock if your clock is running fast otherwise you'll find it running faster.

          Finally, if you get yourself in a mess: Remove the AdjustClock switch in NIST-Time's StartUp entry and reboot - normal service will be resumed.

          This latest version can be got at the first post's link.

          Added: I've just learnt that some systems use 10ms as opposed to 15.625ms ie a frequency of 100HZ as opposed to 64Hz.

          Not to worry, I figured that it may not be universal and use the time adjustment got from GetSystemTimeAdjustment then calculate TimeAdjustment = TimeAdjustment + ClockCorrection before implementing SetSystemTimeAdjustment. Saved by best practice, as always.

          Not quite - I used 64 in the ClockCorrection calculation! I'm now using TimeIncrement which is got from the GetSystemTimeAdjustment API at the same time as TimeAdjustment. TimeIncrement and TimeAdjustment have the same value before any adjustment and the value of TimeIncrement persists.
          Last edited by David Roberts; 3 Jan 2009, 01:38 PM. Reason: Added a note re 100Hz


            I've changed the m.o. on AdjustClock.

            If we found that a further adjustment was warranted then it was as simple matter to run with AdjustClock and the new adjustment. However, if the further adjustment was within the range 276.48ms then it would be effectively ignored as this would fall below the 50 nanosecond ROUNDing threshold.

            The new m.o. will adjust the default. So, if we have a further adjustment to try then it should be added to the first adjustment and the total given to AdjustClock. A further adjustment well inside the 276.48ms may be enough to 'tip the balance' on ROUNDing.

            V1.03 uploaded.

            Added: This wasn't intended but has since occurred to me. If we now use an adjustment within the 276.48ms range then dwTimeAdjustment will be reset to its default value since default + zero = default.
            Last edited by David Roberts; 4 Jan 2009, 02:08 PM.


              Tests have shown that the drift has been reduced to -80ms per six hours ie -320ms per day. This is by no means an exact science and 320 may be regarded as close to 276.48. If we used 156240 then we may get 552.96 [ from 276.48x2] - 320 ie 232.96. However, I shall stay with the algorithm as is - -80 is a heck of a lot better than -1300.
              I couldn't resist it.


              With this switch, which will only work for NT3.5 and later, an information message box is displayed, there is no server query and time setting and any other switches, if they exist, will be ignored. After displaying NIST-Time will shut down.

              I should mention that NIST-Time, if you haven't seen it yet, is an ideal candidate for Run with switches.

              This is what we get.

              For a 64Hz clock the default set up is as the left hand message box. After applying /AdjustClock:-5200, as was done in post #5, /GetSTAdj displays the right hand message box.

              If we regard /AdjustClock analagous to a Class B amplifier then we may regard the next switch as a Class A amplifier - again, only for NT3.5 or later.


              This switch expects a value of 'n' to be a time adjustment. To use 156240, from the quote above, then we'd simply write /AdjustClock#:156240.

              The above expected a clock slow down and this is what happened with 6 hourly queries.

               50ms 06 Jan 09 06:00:05
               68ms 06 Jan 09 12:00:01
               71ms 06 Jan 09 18:00:01
               20ms 07 Jan 09 00:00:01
               19ms 07 Jan 09 06:00:00
              Between 18:00 and 06:00 the machine was pretty much idle and appears to have 'speeded up'. Unfortunately, we must take these figures with a pinch of salt because we are now encroaching on the accuracy of the time got from the time servers which I reckon to be up to 30ms from zero for the most part.

              Notwithstanding the above caveat, if this is a typical day then we are looking at less than 200ms slow per day or less than one second slow in five days. This is quite an improvement on more than five seconds per day fast.

              Is it worth the trouble?

              Perhaps not, but once the calibration has been determined our machines have no more work to do than before an adjustment. In fact, they may have less work to do assuming that because a system refresh cannot occur with periodic adjustment enabled then a reference may not be queried.

              I will not be scheduling a refresh during a Windows session now - another notification area icon bites the dust.

              V 1.04 uploaded.
              Last edited by David Roberts; 7 Jan 2009, 05:19 AM.


                I had fresh install of XP about six months ago and only checked on the TimeServers.dat last week.

                I was only keeping a record of the 'failures' in TimeServers.dat but three of the servers were poor compared with the rest and one of the three was very poor. The stats now record Failures, Successes and Total queries and this confirmed the poor quality of those three; the two AOL and "WiTime, Virginia". The other two WiTime servers were OK. NCAR was also showing less than good results and this is one of the two XP uses in the 'Date and Time Properties'. The status at the NIST site for NCAR was "Very busy". Perhaps it being one of only two with XP may explain why. These four servers have been removed from the NIST-Time list of servers.

                Whilst at the NIST site I noticed some additions to their list so 'grabbed' them for NIST-Time. We now have 22 time servers to randomly choose from.

                I'll keep an eye on the additions to see if they 'pass muster' and report back if not. It is early days yet but of the 40 query sessions so far a second server hasn't been needed.

                NIST-Time v1.05 and new TimeServers.dat uploaded here.
                Attached Files
                Last edited by David Roberts; 6 Dec 2010, 08:59 AM. Reason: sessions not hits