The solution? Calculate the offset between the server clock and client clock at page load time, and from that point on, display the client’s clock corrected by that amount. We also sanity-check the successive differences in the client’s clock, so that if the user changes the time manually (for daylight-savings time, for example), we can reload instead of messing up the calculation. And since the date is on the page, we also reload at midnight (which would cause a spike in server load then if many users left their browsers open, but no other ill effects).
The local and server clocks are saved in a cookie, so that we can tell if we’re just reloading a locally cached page (since the stale server clock embedded in the page will match the cookie). We should have been able to use headers to prevent caching and force a reload, but they didn’t have any effect when using the Back button in tested versions of IE for Windows (but not other browsers). The cookie method saves server traffic anyway.
If we used repeated setTimeout()s with a fixed interval of one second to update the clock, the display would gradually start to lag behind real time then skip ahead two seconds at once, giving a jerky appearance. We could use setInterval() to avoid this, but if the seconds were hidden, the clock would update sixty times more often than necessary, bogging down slow computers. We could then decide to switch the interval to one minute whenever the seconds were hidden, but the minute display would change over too late (by an average of 30 seconds), depending on how many seconds we were into the minute on page load.
There is a solution that avoids all these problems: after each update, calculate the number of milliseconds remaining until the next minute or second boundary (depending on whether seconds are hidden) and use setTimeout() to schedule the update function for that exact time.
There is one remaining problem, to which Macintouch (2002-10-12) recently alerted me. In addition to the daylight-savings bug in Mac IE, which the code successfully works around, there is a nasty sleep bug, which in my tests reproducibly caused local time to stand still over the entire interval from sleep to wake. So if the clock is already loaded when the machine goes to sleep, it ends up being slow after wake, with no jump in local time to allow the code to even detect that sleep occurred. Reloading the page updates the time from the server and fixes the problem. Any ideas on how to fix this in code would be appreciated; please use my contact page.
Version 2.1.2 fixes an intermittent bug in loading the clock in the PHP version. More details to come.
|Compatibility||Browser: Internet Explorer 4 and up, Netscape 4 and up, Mozilla, and other DOM-compliant browsers. Server: Windows NT 4 and 2000 with IIS (for the ASP version), any OS with Apache and PHP 4 (for the PHP version; tested under Linux and Mac OS X).|
|Techniques||Client-side cookie parsing, setTimeout(), cross-browser DHTML, ASP to PHP translation.|
|Download||[View Source - ASP] | [View Source - PHP]|
|Installation||Copy the page content from one of the above links and paste it into a new empty file in a text editor, saving the result on your web server with the appropriate filename extension (".asp" or ".php"). Reposition the two <div>s and add your own content to suit.|