0

I am using the following script below, and what I am trying to do is to set a custom time to the script and for it to auto update without the need to re-set the time each time. (I only want to set the time once and want my script to keep track of the time and display it)

When I run the script it displays: NaN:NaN:NaN AM

My Code is as follows:

<div id="js_clock"> display clock here </div>

 <script language="javascript">
    function js_clock(clock_time)
    {   
         var clock_hours = clock_time.getHours();  
         var clock_minutes = clock_time.getMinutes();  
         var clock_seconds = clock_time.getSeconds();  
         var clock_suffix = "AM";     
         if (clock_hours > 11){
         clock_suffix = "PM";
         clock_hours = clock_hours - 12;
         }
         if (clock_hours == 0){
         clock_hours = 12;
         }

         if (clock_hours < 10){
         clock_hours = "0" + clock_hours;
         }

         if (clock_minutes < 10){
         clock_minutes = "0" + clock_minutes;
         }

         if (clock_seconds < 10){
         clock_seconds = "0" + clock_seconds;
         }

         var clock_div = document.getElementById('js_clock');
         clock_div.innerHTML = clock_hours + ":" + clock_minutes + ":" + clock_seconds + " " + clock_suffix;
         setTimeout("js_clock()", 1000);
    }

     var serverTime = new Date("09:20:50");
     js_clock(serverTime);
 </script>
Aaron
  • 3,389
  • 12
  • 35
  • 48

4 Answers4

2

I think you've forgotten passing an argument to js_clock(). Maybe you shoud do:

setTimeout(
    function() {
        //Call the function again updating seconds by 1
        js_clock(
            new Date(
                clock_time.getFullYear(), 
                clock_time.getMonth(), 
                clock_time.getDate(), 
                clock_time.getHours(), 
                clock_time.getMinutes(), 
                clock_time.getSeconds() + 1
             )
        );
    }, 
    1000
);

EDIT: I missed the point this can be done with a single function call:

setTimeout(
    function() {
        js_clock(new Date(+clock_time + 1000));
    },
    1000
);

The +clock_time statement converts the Date object to milliseconds from the UNIX Epoch, so updating the time is as simple as summing 1000 milliseconds. Thanks to user RobG ;-)

Claudi
  • 5,224
  • 17
  • 30
  • 1
    You [shouldn't pass strings to `setTimeout()`](http://stackoverflow.com/questions/6081560/is-there-ever-a-good-reason-to-pass-a-string-to-settimeout); it is [evil, like `eval()`](http://stackoverflow.com/a/6232610/82548). – David Thomas Aug 05 '12 at 23:35
  • 1
    Good grief, the "eval is evil" thing needs a rest. Sure it's not optimal, but it isn't evil. Far better to comment on why those 6 function calls are made instead of none: `new Date(+clock_time + 1000)` – RobG Aug 06 '12 at 01:43
  • @RobG: my link text was to paraphrase the answer to which I linked, rather than a profound belief in the concept of `eval() === evil`. And the only reason I linked to those other pages was to lend support for my request as regards not passing strings to `setTimeout`. Perhaps I should have better chosen my words, though. – David Thomas Aug 07 '12 at 14:59
  • @claudix You ommited the 2nd param for `setTimeout` in your edit - edited. – Pere Nov 26 '15 at 13:09
2

You have a problem creating the date, new Date("09:20:50"); returns Invalid Date.

if you want to set hours minutes and seconds use

new Date(year, month, day [, hour, minute, second, millisecond ])

or take a look here.

Also you forgot to pass a date to the setTimeout, try:

setTimeout(function() {
    js_clock(new Date(/*pass hours minutes and seconds here*/))
}, 1000);
nicosantangelo
  • 13,216
  • 3
  • 33
  • 47
0

WAIT! just realised, this is still not showing the correct time. The error is gone, but the time isn't what you are looking for.

window.js_clock = function js_clock(clock_time) {
    var clock_hours = clock_time.getHours();
    var clock_minutes = clock_time.getMinutes();
    var clock_seconds = clock_time.getSeconds();
    var clock_suffix = "AM";
    if (clock_hours > 11) {
        clock_suffix = "PM";
        clock_hours = clock_hours - 12;
    }
    if (clock_hours === 0) {
        clock_hours = 12;
    }

    if (clock_hours < 10) {
        clock_hours = "0" + clock_hours;
    }

    if (clock_minutes < 10) {
        clock_minutes = "0" + clock_minutes;
    }

    if (clock_seconds < 10) {
        clock_seconds = "0" + clock_seconds;
    }

    var clock_div = document.getElementById('js_clock');
    clock_div.innerHTML = clock_hours + ":" + clock_minutes + ":" + clock_seconds + " " + clock_suffix;
    setTimeout("js_clock(new Date())", 1000);
}

var serverTime = new Date("09:20:50");
window.js_clock(serverTime);​
bPratik
  • 6,894
  • 4
  • 36
  • 67
  • Don't use `setTimout` with a string. See http://stackoverflow.com/questions/6081560/is-there-ever-a-good-reason-to-pass-a-string-to-settimeout. – Zeta Aug 05 '12 at 23:40
  • @bPratik - This seems to get the time from my computer. I want to be able to manually set the time and it to keep updating the time every second based on the time I set. – Aaron Aug 05 '12 at 23:51
0

Your code has some serious flaws, such as the following.

setTimeout doesn't run at exactly the interval set, but as soon as it can afterward so this clock will slowly drift, sometimes by a lot.

Passing a string to Date and expecting it to be correctly parsed is problematic. In ECMA-262 ed 3 it was entirely implementation dependent, in ES5 the string is required to be a custom version of the ISO8601 long format (but note that not all browsers in use support ES5).

Lastly, if the client is busy, the function may not run for several seconds so the clock needs to be based on the client clock, then ajusted for the time difference.

The following function does all the above.

<script type="text/javascript">
var customClock = (function() {

  var timeDiff;
  var timeout;

  function addZ(n) {
    return (n < 10? '0' : '') + n;
  }

  function formatTime(d) {
    return addZ(d.getHours()) + ':' +
           addZ(d.getMinutes()) + ':' +
           addZ(d.getSeconds());
  }

  return function (s) {

    var now = new Date();
    var then;

    // Set lag to just after next full second
    var lag = 1015 - now.getMilliseconds();

    // Get the time difference if first run
    if (s) {
      s = s.split(':');
      then = new Date(now);
      then.setHours(+s[0], +s[1], +s[2], 0);
      timeDiff = now - then;
    }

    now = new Date(now - timeDiff);

    document.getElementById('clock').innerHTML = formatTime(now); 
    timeout = setTimeout(customClock, lag);
  }
}());


window.onload = function() {
  customClock('09:20:50');
}

</script>

<div id="clock"></div>
RobG
  • 142,382
  • 31
  • 172
  • 209