This clock sits on a Web page and continuously displays the correct
time, despite the scourges of inaccurate client clock settings
and buggy JavaScript implementations. Clicking on the clock toggles
the seconds display. Even while showing only the minutes, it is
still generally accurate to about one second. (The error may be
greater if there is a long delay between hitting Reload/Refresh
and actually starting to receive the page. Specifically, the time
interval between the server starting to execute the page's scripting
code and client executing the first block of inline JavaScript
code is lost.) For accuracy, the server itself should be synchronized
to an NTP time server.
[Watch the Clock]
(Note: uses cookies.)
Why all this work?
Why is displaying the current time difficult? For one thing,
we don't want the clock to stand still after the page loads, even
when hiding the seconds display. After a few minutes (or when
the user follows a link and then clicks Back) it would become
rather wrong. We could force the entire page to reload every minute,
but that would cause a significant increase in server load for
a busy home page, and would annoy the users if they happened to
be trying to navigate the page at the time. So the solution is
for client-side JavaScript and cross-browser DHTML to keep the
clock current.
First Cut
The simplest method from this point is to have the JavaScript
code read the current time from the user's clock. For an intranet
home page, I actually did this, only to receive complaints from
users that the clock on our home page was wrong--very, very wrong,
sometimes off by days. Of course, those users really needed to
fix their own clocks, but even if all of them did so, there were
many more who didn't notice at all because their clocks weren't
quite wrong enough. And why would they even think to distrust
the home page? The clock on there certainly matched their own
computer clock well enough. If any users did want to correct their
own clocks or watches, it would certainly help to have an accurate
clock to go by, not just one that parroted inaccurate times from
their own computers and made them look official. Complicating
matters further, a long-standing JavaScript
bug in IE for Mac threw times off by exactly one hour during
Daylight Savings Time and by even more if the machine had been
to sleep.
Second Cut
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).
All the Implementation Wrinkles
Cookies and Caching
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.
setTimeout()
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.
JavaScript
If the browser doesn't support JavaScript 1.2, the clock will
still show up, but will be static.
Getting the Server's Clock
There is a small amount of server-side support code. I provided
it in two languages: ASP-JScript (best for Windows IIS servers)
and PHP (for all other servers). The ASP version, through its
use of JavaScript instead of VBScript, has the interesting property
of allowing the server-side time formatting function to be an
exact copy of the client-side function. In PHP, the function had
to be rewritten, though it did end up shorter. For fun, you can
compare the two.
Mac IE Sleep Bug
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.
Update
Version 2.1.2 fixes an intermittent bug in loading the clock
in the PHP version. More details to come.
| Language |
JavaScript (client-side) and either ASP-JavaScript
or PHP (server-side). |
| 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. |
| Cost |
Free. |
| 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. |