'New Improved' script for syncing clock 
Author Message
 'New Improved' script for syncing clock

I posted a version of this script 3-4 weeks ago. This one is better.
If you wanted to fully automate the time syncing, the old version had to
be scheduled which is less than ideal for a dial-up connection. This
version is written to be started with a shortcut in the startup folder,
or can run as a service using srvany.exe.

The old version only worked on systems using a mm/dd/yy date format.
Not good.  This version should work for any locale. But unless I missed
something in the docs, it's not as easy doing this in jscript as it is
in VBScript. Am I doing it the hard way?  I think DateValue(Now) is all
you need with vbscript to get something that can be used with the date
command.

The old version used xmlhttp to test for being online, mainly because
ping wasn't working on my system when I tried it. I later discovered
that 'http.open("OPTIONS"," http://www.*-*-*.com/ ",false);' works better
than the 'http.open("GET"," http://www.*-*-*.com/ ;,false);' I used
before, but it's still about 1/10th second slower than a first ping
(~.6s vs .5s with my connection). Using ping makes it easier to try 2 or
3 sites too, so now that ping is working on my system again I use it in
the new version.  [Torgeir: still can't ping www.hydro.com though.]

This version has other improvements too, like waiting for RAS inactivity
before doing a sync thereby increasing accuracy.

I'm hoping someone using XP will try it out and let me know if it works.
I'm "sure" there's no bugs ;-)  but if there are I'd appreciate hearing
about those too.

--
Jim Taylor

/*
Tested on Windows 2000.  May or may not work with XP.
Set the time server using the command NET TIME /SETSNTP:time.nist.gov

Command line arguments (optional):

        arg0
                0: (or not present) Do a time sync if possible and exit. (No RAS activity check.)
                1: Remain loaded until there's one good sync, then exit.
                2: Remain loaded and sync once per x hours or days.
        arg1
                0: (or not present) Allow all popups appropriate for the arg0 value.
                1: Block most popups.

Set shortcut target to: wscript "<path>\jsync.js" arg0 arg1.
*/

var title = "jsync.js";
var logfile = "jsync.log";      //If a path is added remember to use \\ for a backslash.
var PingSites = new Array ("time.nist.gov", "www.yahoo.com", "www.zdnet.com");
var MaxChange = 50;             //Warn user if a time correction exceeds this limit in seconds. Not blocked by arg1.
var QuietTime = 20;             //if arg0>0, number of seconds that RAS must have no activity before doing a time sync.
var delay = 0;                  //if arg0>0, number of seconds to display the warning popup before syncing. 0=no warning.

var fso = new ActiveXObject("Scripting.FileSystemObject");
var oSh = WScript.CreateObject("WScript.Shell");

var oEnv = oSh.Environment("PROCESS");
var tempfile = oEnv("TEMP") + "\\$jsync$.tmp" ;

var oArgs = WScript.Arguments;
var arg0 = (oArgs.length > 0)? oArgs(0) : 0;
var arg1 = (oArgs.length > 1)? oArgs(1) : 0;

var pop1, LockedOut, oLogfile, GoodSync, answer, TimeError, NewTime, TimeWas;
var minute=60*1000, hour=60*minute, ForReading=1, ForAppending=8;

while (true){
        answer = GoodSync = false;
        do{
                pop1 = LockedOut = false;
                if (arg0) WaitForQuietRAS(QuietTime);
                try{
                        oLogfile = fso.OpenTextFile(logfile, ForAppending, true);
                }
                catch(e){
                        LockedOut = true;
                }
                if (!LockedOut){
                        if (ping()){
                                if (!answer) answer = NotifyUser();
                                switch (answer){
                                        case -1 : WaitForQuietRAS(QuietTime);       //timed out - do checks again because of the delay.
                                                  if (ping()) GoodSync = SyncTime(); break;
                                        case  2 : GoodSync = true; break;           //Cansel button was pushed.
                                        default : GoodSync = SyncTime();            //OK button was pushed or the popup wasn't opened.
                                }
                        }
                        else if (!arg0) pop1 = new Array("Unable to access the Internet.",4,64);
                        oLogfile.close();
                        if (pop1){
                                oSh.popup(pop1[0], pop1[1], title, pop1[2]);
                                if (!arg1 && GoodSync) pop2();
                        }
                }
                if (!arg0 || arg0==1 && GoodSync)
                        WScript.quit();
                WScript.sleep(4*minute);
        }
        while (!GoodSync);
        WScript.sleep(12*hour);

Quote:
}

function NotifyUser()
{
        if (arg0 && !arg1 && delay > 0){
                var d = (delay + QuietTime) * 1000;
                var when = new Date(new Date().getTime() + d).toLocaleString();
                when = when.substr(when.indexOf(":")-2);
                var s = "The clock will be synchronized to a time server at " + when + ".\n"
                      + "(Any RAS activity in the " + QuietTime + " seconds preceding the sync will cause a delay.)\n\n"
                      + "Click on OK to synchronize the clock immediately, click on Cancel to cancel the event.";
                var BtnCode = oSh.Popup(s, delay, title, 65);
                return BtnCode;  //-1=timeout, 1=OK, 2=Cansel
        }
        return 0;

Quote:
}

function pop2()
{
        var d = Math.round( (TimeWas - new Date())/1000 );
        var s = "This window will close when the PC's date/time has reached its\n"
          + "previous maximum value, " + TimeWas.toLocaleString() + ".";
        if (d > 5 && d/60/60 < 10) oSh.popup(s, d, title, 64);

Quote:
}

function SyncTime()
{
        var i, f, index, result;
        NewTime = 0;
        TimeWas = new Date();
        do{
                if (NewTime) MoveTime(TimeError + 200);
                oSh.run("%comspec% /c w32tm.exe -once > " + tempfile, 0, true);

                f = fso.OpenTextFile(tempfile, ForReading);
                w32tm = f.ReadAll();
                f.close();
                fso.DeleteFile(tempfile);

                var failed = new Array();
                failed[0] = new Array("connect failed",     "w32tm reports: Unable to connect to server.");
                failed[1] = new Array("send failed",        "w32tm reports: Received no response from server.");
                failed[2] = new Array("source failed",      "w32tm reports: Time source failed to produce usable timestamp.");
                failed[3] = new Array("Cannot synchronize", "w32tm reports: Cannot synchronize.\n\nHas a time server been set?");
                failed[4] = new Array("not get delay",      "w32tm reports: Erratic round trip delays, so time was not set.");
                for (i in failed){
                        if (w32tm.indexOf(failed[i][0]) != -1){
                                if (!arg0) pop1 = new Array(failed[i][1],0,48);
                                return false;
                        }
                }
                if (!NewTime){
                        index = w32tm.indexOf("ClockError");
                        TimeError = parseInt(w32tm.substring(index+12, w32tm.indexOf("\n",index)-1));
                }
                index = w32tm.indexOf("BEGIN:SetTimeNow")+18;
                result = w32tm.substring(index+12, w32tm.indexOf("\n",index)-1);
                switch (true){
                        case result.substr(0,3)  == "END"    : NewTime = "Not changed"; break;
                        case result.substr(3,7) == "Skewing" : NewTime = 1; break;
                        case result.substr(3,4)  == "Time"   : NewTime = GetLocalDT(result.substr(8,result.length-1)); break;
                        default :
                                if (!arg0) pop1 = new Array("Script Error " + NewTime,0,16);
                                return false;
                }
        }
        while (NewTime==1);
        ShowAndLog();
        return true;

Quote:
}

function ShowAndLog()
{
        var day=1000*60*60*24;
        if (Math.abs(TimeWas - NewTime) > 24*day)                   //Fix for "ClockError" in the w32tm output being a signed
                TimeError = Math.round((TimeWas - NewTime)/1000)*1000;  //32-bit value that overflows if error > 24.86 days.

        var server = oSh.RegRead("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\W32Time\\Parameters\\ntpserver");
        var TimeIs = new Date(TimeWas.getTime() - TimeError);
        var tail = (NewTime == "Not changed")? "not corrected" : "corrected";
        var SlowOrFast = (TimeError > 0)? " fast" : " slow";
        var strPopUp = "SNTP time server:\t" + server + "\n\n";
        var strLog  = GetLogTime() + " ";

        if (TimeError == 0){
                strPopUp += "Time difference:\tCorrect to the millisecond.\n";
                strLog   += " no time error.";
        }
        else{
                strPopUp += "Time difference:\t" + GetText(TimeError) + SlowOrFast + ".  (" + tail + ")\n";
                strLog   += SlowOrFast + ", " + GetText(TimeError) + ", " + tail + ".";
        }
        oLogfile.Write(strLog + "\r\n");

        if (Math.abs(TimeError) > 1000)
                strPopUp += "\nLocal time was:\t" + TimeWas.toLocaleString();
        strPopUp += "\nLocal time is:\t"  + TimeIs.toLocaleString();

        if (Math.abs(TimeError)/1000 > MaxChange){
                strPopUp += "\n\n**This change exceeded the " + MaxChange + " second warning level set in the script**";
                pop1 = new Array(strPopUp,0,48);
        }
        else if (!arg1)
                pop1 = new Array(strPopUp,0,64);

Quote:
}

function GetLogTime()
{
        var p = (GetParts(new Date()));
        return p[0] + "." + p[1] + "." + p[2] + " " + p[3] + ":" + p[4];

Quote:
}

function GetLocalDT(UTCtime)    //input format (from w32tm output): "8/20/2002   18:22:17:465"
{
        var s = UTCtime.split(/ |\/|:/);
        var offset = new Date().getTimezoneOffset();
        return new Date(s[2], s[0]-1, s[1], s[3], s[4]-offset, s[5]);

Quote:
}

function MoveTime(milliseconds)      //positive number moves time back
{
        var WillBeDate = new Date(new Date().getTime() - milliseconds);
        var p = GetParts(WillBeDate);
        oSh.run("%comspec% /c time " + p[3] + ":" + p[4] + ":" + p[5], 0, true);
        oSh.run("%comspec% /c date " + GetShortDateFormat(WillBeDate), 0, true);

Quote:
}

function GetShortDateFormat(d)         //arranges month, day, year in short date order
{
        var i, j, s="", f, sf;
        var a = new Array();
        a[0]  = new Array("y", d.getFullYear() );
        a[1]  = new Array("M", d.getMonth()+1 );
        a[2]  = new Array("d", d.getDate() );
        f = oSh.RegRead("HKEY_CURRENT_USER\\Control Panel\\International\\sShortDate");
        sf = f.split(/\.|\/|-/);
        for (i in sf)
                for (j in a)
                        if (sf[i].substr(0,1) == a[j][0])
                                s += a[j][1] + "-";
        return s.replace(/-$/, "");

Quote:
}

function GetParts(d)
{
        function pad(n)
        {
                return(n = (n < 10)? "0" + n : n);
        }
        var parts = new Array();
        parts.push(d.getFullYear());         //parts[0]
        parts.push(pad(d.getMonth() + 1));   //parts[1]
        parts.push(pad(d.getDate()));        //parts[2]
        parts.push(pad(d.getHours()));       //parts[3]
        parts.push(pad(d.getMinutes()));     //parts[4]
        parts.push(pad(d.getSeconds()));     //parts[5]
        return parts;

Quote:
}

function GetText(n)
{
        var seconds, minutes, hours, days, s="";
        var minute=60*1000, hour=60*minute, day=24*hour;
        var n = (n < 0)? -n : n;
        switch (true){
                case n >= day    : days    = Math.floor(n/day);    n -= day * days;
                case n >= hour   : hours   = Math.floor(n/hour);   n -= hour * hours;
                case n >= minute :
...

read more »



Thu, 24 Feb 2005 05:25:29 GMT  
 'New Improved' script for syncing clock


et.att.removethis.net> posted at Sat, 7 Sep 2002 21:25:29 :-

Quote:

>The old version only worked on systems using a mm/dd/yy date format.
>Not good.  This version should work for any locale. But unless I missed
>something in the docs, it's not as easy doing this in jscript as it is
>in vbscript. Am I doing it the hard way?  I think DateValue(Now) is all
>you need with vbscript to get something that can be used with the date
>command.

Do you really need to use any user-locale-dependent functions?

AIUI, the server formats should be well-specified and are not
necessarily user-locale; and you can display, world-wide, in the format
shown by [Sun,] 2002-09-08 13:14:09

--

  <URL:http://www.jibbering.com/faq/> FAQ for comp.lang.javascript by Jim Ley.
  <URL:http://www.merlyn.demon.co.uk/js-index.htm>   JS maths, dates, sources.
  <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/JS/&c., FAQ topics, links.



Thu, 24 Feb 2005 20:13:40 GMT  
 'New Improved' script for syncing clock
On Sun, 8 Sep 2002 13:13:40 +0100, Dr John Stockton

Quote:



> et.att.removethis.net> posted at Sat, 7 Sep 2002 21:25:29 :-

> >The old version only worked on systems using a mm/dd/yy date format.
> >Not good.  This version should work for any locale. But unless I missed
> >something in the docs, it's not as easy doing this in jscript as it is
> >in vbscript. Am I doing it the hard way?  I think DateValue(Now) is all
> >you need with vbscript to get something that can be used with the date
> >command.

> Do you really need to use any user-locale-dependent functions?

> AIUI, the server formats should be well-specified and are not
> necessarily user-locale; and you can display, world-wide, in the format
> shown by [Sun,] 2002-09-08 13:14:09

The problem I had was with the dos date command which apparently uses
the short date format for the locale the system is set to. With my
locale set to English(US) it wants the date entered as mm-dd-yy. For
English(UK) it expects dd-mm-yy which is also an option for
English(US).

The vbscript functions Date and DateValue return the date in a short
date format that can be used with the dos date command. If there's
anything like it for jscript, I missed it. In my script I wrote
GetShortDateFormat() to get the short date format from the registry
and rearrange a jscript date to work with the date command. Is there
an easier way?

The only reason the script uses a dos date command is that originally
I moved the time back 4 minutes if the time error was in the .013 ms
to 3 minute fast "skew" range that 'w32tm -once' doesn't handle right
(it just leaves the time unchanged) so that a second w32tm -once
command would set the time correctly. The command is needed only if a
sync is done within a few minutes past midnight and the time error is
large enough to take the new time back past midnight. With the latest
version I don't set the time as far back - just a second or so on the
slow side is enough - but it's still possible in the 0-3 minutes past
midnight time frame that the date will need to be changed.

To answer your question, I guess you could eliminate having to change
the date if you'll willing to add up to a 3 minute delay for syncs
done within 3 minutes past midnight. That wouldn't matter for
background syncs but would be irritating if you just happen to pick
midnight for a manual sync and the time error is 3 minutes fast.

Have you tried the script on your system?  If so, see any problems
with it?

--
Jim



Fri, 25 Feb 2005 03:53:55 GMT  
 'New Improved' script for syncing clock


et.att.removethis.net> posted at Sun, 8 Sep 2002 19:53:55 :-

Quote:
>On Sun, 8 Sep 2002 13:13:40 +0100, Dr John Stockton



>> et.att.removethis.net> posted at Sat, 7 Sep 2002 21:25:29 :-

>> >The old version only worked on systems using a mm/dd/yy date format.
>> >Not good.  This version should work for any locale. But unless I missed
>> >something in the docs, it's not as easy doing this in jscript as it is
>> >in vbscript. Am I doing it the hard way?  I think DateValue(Now) is all
>> >you need with vbscript to get something that can be used with the date
>> >command.

>> Do you really need to use any user-locale-dependent functions?

>> AIUI, the server formats should be well-specified and are not
>> necessarily user-locale; and you can display, world-wide, in the format
>> shown by [Sun,] 2002-09-08 13:14:09

>The problem I had was with the dos date command which apparently uses
>the short date format for the locale the system is set to. With my
>locale set to English(US) it wants the date entered as mm-dd-yy. For
>English(UK) it expects dd-mm-yy which is also an option for
>English(US).

Setting date+time back might cause problems, but ISTM that setting date
back could cause more.

It seems worthwhile, where possible, to schedule the time check, to a
time when nothing else is likely to be scheduled; say xx:13:46.  And if
a major change is needed, perhaps the user should do it by hand, when
thought safe.

Quote:
>The vbscript functions Date and DateValue return the date in a short
>date format that can be used with the dos date command. If there's
>anything like it for jscript, I missed it. In my script I wrote
>GetShortDateFormat() to get the short date format from the registry
>and rearrange a jscript date to work with the date command. Is there
>an easier way?

On 97% of days, one could possibly read the date and have a fair guess
at the actual format.

Quote:
>Have you tried the script on your system?  If so, see any problems
>with it?

No; your software exceeds mine, so I can only make generic comments.

I use Turnpike to connect to the Net; that has optional automatic
synchronisation of the PC; and I have a vague feeling that internally it
makes allowance for this, if/as needed for minimum confusion.

--

 Web  <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
 PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.txt
 Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.



Fri, 25 Feb 2005 22:04:14 GMT  
 'New Improved' script for syncing clock
On Mon, 9 Sep 2002 15:04:14 +0100, Dr John Stockton

Quote:

> Setting date+time back might cause problems, but ISTM that setting date
> back could cause more.

Too bad there's not a command for setting both at one time. I haven't
seen any problem yet but if I do I'll take the date command out and
maybe just have a popup that says "Try again in a few minutes" if I
try to do a manual sync too close to midnight. That would be a little
unusual though, a time sync program that can't sync any second of the
day.

Quote:
> It seems worthwhile, where possible, to schedule the time check, to a
> time when nothing else is likely to be scheduled; say xx:13:46.  And if
> a major change is needed, perhaps the user should do it by hand, when
> thought safe.

Scheduling is fine if you leave your computer on 24/7. I don't, which
is why I need a program that loads when I boot up, then waits for when
I'm online and a quiet RAS before syncing.

I never did add a warning about how much a time change would be in
advance of doing it. It's possible using w32tm -once -test but the
only time I've seem a major change is when I've set the clock a week,
month or year ahead or back for testing. It wouldn't matter for
anything I do anyway.

Quote:
> On 97% of days, one could possibly read the date and have a fair guess
> at the actual format.

No sure what you mean there. The dos date command can't guess.

Maybe I've just become more aware but this syncing to NIST stuff seems
to be everywhere lately, in cheap wall clocks and clock radios, $50
wris{*filter*}ches, perhaps even in new cars.  They might even be more
accurate than my PC clock with daily syncs because my PC gains about
12 seconds/day, meaning that on average it's 6 seconds fast. Here
lately though I've been syncing 'much' more than once per day testing
this script out.

--
Jim



Sat, 26 Feb 2005 06:43:15 GMT  
 'New Improved' script for syncing clock


et.att.removethis.net> posted at Mon, 9 Sep 2002 22:43:15 :-

Quote:

>> On 97% of days, one could possibly read the date and have a fair guess
>> at the actual format.
>No sure what you mean there. The dos date command can't guess.

If DATE gives   greater-than-12 / ## / ####   then assume US format.
If DATE gives   ## / greater-than-12 / ####   then assume UK format.

Otherwise, it may be reasonable to assume that the Month is right; and
97% of the time Month != Day.

--

 Web  <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
 PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.txt
 Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.



Sat, 26 Feb 2005 20:58:16 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Script for syncing clock to a time server

2. very stupid 5 o'clock time to go home question

3. New: Web 'PostScript'

4. Hiding the 'New' Record

5. Opening IE (I'm new at WSH, like you couldn't tell

6. New and improved stuff at Win32 Scripting!!!!

7. New and improved stuff at Win32 Scripting!!!!

8. Question: Create a new script or application, I'm clueless

9. VB Script 5.5 What's New?

10. New IE6 beta can't install Visual Basic scripting support

11. Brand Spankin' New Scripting (WSH) Type Person

12. VB script runtime error '800a01a8'

 

 
Powered by phpBB® Forum Software