Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I use the following PHP Code to output the user's local time and the servers time (office time). $local_time and $remote_time are the corresponding UNIX timestamps:

<span class='icon-time' data-time='<?php echo $local_time; ?>' id='local-time'>
Local : <?php echo date('D, M j, h:ia', $local_time); ?></span><br />
<span class='icon-time text-<?php

echo (6 > date('N') && 9 <= date('G') && date('G') <= 17) // change class if open/closed
    ? 'success'
    : 'error';

?>' data-time='<?php echo $remote_time; ?>' id='remote-time'>
Office : <?php echo date('D, M j, h:ia', $remote_time); ?></span>

I then have the following JavaScript to update the clocks in real-time:

// update local/office clocks
window.setInterval(function () {

    lclock = $('#local-time');
    rclock = $('#remote-time');

    // convert to UNIX timestamp, add 60 secs since setInterval() will no start onload but after 60 secs
    ltime = new Date((lclock.data('time') * 1000) + 60000); 
    rtime = new Date((rclock.data('time') * 1000) + 60000);

    lhours = ltime.getHours();
    rhours = rtime.getHours();

    // make 12hr time format and left-pad with zero
    lshours = ((0 === lhours) ? 12 : (lhours - ((12 < lhours) ? 12 : 0)));
    rshours = ((0 === rhours) ? 12 : (rhours - ((12 < rhours) ? 12 : 0)));

    lmins = ltime.getMinutes();
    rmins = rtime.getMinutes();

    rday = rtime.getDay();

    // determine if office is closed and change class
    ostatus = 'icon-time ' + ((6 > rday && 0 < rday && 9 <= rhours && 17 >= rhours)
        ? 'text-success'
        : 'text-error');

    // update clock, increment timestamp by 60 secs
    lclock.text('Local : ' + days[ltime.getDay()] + ', ' 
    + months[ltime.getMonth()] + ' ' + ltime.getDate() + ', ' 
    + ((10 > lshours) ? '0' + lshours : lshours) + ':' 
    + ((10 > lmins) ? '0' + lmins : lmins) 
    + ((12 <= lhours) ? 'pm' : 'am')).data().time += 60;

    // update clock, change CSS class, increment timestamp by 60 secs
    rclock.text('Office : ' + days[rtime.getDay()] + ', ' 
    + months[rtime.getMonth()] + ' ' + rtime.getDate() + ', ' 
    + ((10 > rshours) ? '0' + rshours : rshours) + ':' 
    + ((10 > rmins) ? '0' + rmins : rmins) 
    + ((12 <= rhours) ? 'pm' : 'am')).attr('class', ostatus).data().time += 60;

}, 60000);

It works great. However, after a few hours the time can end up being off by up to -7 minutes. I tried caching as many objects as I could and optimizing it the best I could to reduce the amount of variable value assignments, and used chaining as well, but can't see how else to speed it up to make it not lose time.

  • How can I optimize this further, in either my method, code being used, or is there something I am doing wrong?
share|improve this question
add comment

1 Answer

up vote 4 down vote accepted

The thing to understand with setInterval() and other timer-based functions in general is that they do not guarantee precise timing. You request an interval of 60000ms, and your mistake is assuming that what you get is in fact an interval of exactly 60000ms.

The main trick is to measure the actual amount of elapsed time between intervals, rather than assuming that each interval occurs exactly 60000ms after the previous one. Do that and you should see better results.

Note that there may also be secondary effects caused by the execution time of your code itself. To get around that, instead of adding deltas on each invocation you could track the initial starting timestamp at which your script starts running, and then just always compute the total amount of time that has elapsed between that starting timestamp and now, and add that amount to the starting timestamp when displaying the time. That should give you very accurate output, and it solves the problem of the imprecise timer as well.

Here's a similar JavaScript timer that I coded awhile back that you can use as a reference.

share|improve this answer
1  
Excellent suggestions! I'll re-work it and see how it works out and will be back. Thank you. –  cryptic ツ Feb 1 '13 at 6:22
    
Re-did code per your suggestions and working great. –  cryptic ツ Feb 1 '13 at 10:02
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.