Make a Javascript Clock

Although there are many ways to make a clock using Javascript, most use Javascript’s date() object and the setInterval() method. In this tutorial we’ll start by building a clock using these simple functions. Then we’ll explore some interesting ways of optimizing our clock, and hopefully learn a whole bunch of Javascript along the way.


Getting the current time

Let’s kick things off by getting the current time with Javascript. To do so, we will need the Javascript date() object. Remember that this gets the client-side time, e.g. the time in the user’s browser, not the actual time on the server. Client-side time is great for situations like ours, since it takes away any time-zone localization problems.

The date() object is simple enough to use, just instantiate it:

var d = new Date();

Then you can call any properties of this object, getMinutes(), getDay(), getDate(), etc.

In our case we’ll want the hour, minutes, and seconds. Let’s put them all in a single string:

var d = new Date();
var timeStr = d.getHours() + d.getMinutes() + d.getSeconds();

This looks great, but what if it’s 12:04:08? These values are all integers, so 12:04:08 would become 1248, and mess up our time string. In order to keep the time strings universal, we’ll have to add some leading zeros.

While Javascript has a nice function to control the number of trailing zeros of a decimal, there is no native way to control leading zeros of an integer. For these situations, a padZeros function comes in handy:

function padZeros(theNumber, max) {
    var numStr = String(theNumber);
    
    while ( numStr.length < max) {
        numStr = '0' + numStr;
    }
    
    return numStr;
}

Using this function, we can get a properly formatted time string:

var timeStr = d.getHours() + padZeros(d.getMinutes(), 2) + padZeros(d.getSeconds(), 2);

Note that the padZeros function was not applied to the hours, because leading zeros in the hours do not effect the value of the time string.

Adding the clock CSS

In order to allow our clock to look any way we want, let’s use CSS background images for the digits. First we’ll set up some default attributes for all digits. Then, to avoid any image sourcing issues, we’ll use a single background image for all the digits, and just define a different background-position for each digit:

#jsClock {
    height:100px;
}

#jsClock DIV {
    background-repeat: no-repeat;
    background-image: url(digits.png);
    width:70px;
    height:100px;
    margin-right:5px;
    float:left;
}

.digit-0 { background-position: 0 0; }
.digit-1 { background-position: -70px 0; }
.digit-2 { background-position: -140px 0; }
.digit-3 { background-position: -210px 0; }
.digit-4 { background-position: -280px 0; }
.digit-5 { background-position: -350px 0; }
.digit-6 { background-position: -420px 0; }
.digit-7 { background-position: -490px 0; }
.digit-8 { background-position: -560px 0; }
.digit-9 { background-position: -630px 0; }
.digit-colon { background-position: -700px 0; }

If you want to use the digit artwork we’re using in this tutorial, get it here, otherwise make sure to adjust the width and height values for #jsClock and #jsClock DIV.

Now, let’s add some really simple markup:

<div id="jsClock"></div>

You might be wondering why we didn’t put any digits within #jsClock. This is because we are going to add them using Javascript.

Setting up the clock DIV with Javascript

If we put our Javascript in the <head> and try to target the clock object using document.getElementById('jsClock'), it will throw an error that it is undefined. This is because at the time this Javascript is called, the clock element doesn’t exist yet.

In order to get around this problem, we need to fire off the Javascript after the document loads, which is best done using an event handler function:

function addEvent(obj, evType, fn){ 
    if (obj.addEventListener){ 
        obj.addEventListener(evType, fn, false); 
        return true; 
    } else if (obj.attachEvent){ 
        var r = obj.attachEvent("on"+evType, fn); 
        return r; 
    } else { 
        return false; 
    }
}

With this, we can schedule a function to fire once the window loads:

function init() {
    var theClock = document.getElementById('jsClock');
}

addEvent(window, 'load', init);

Now that we can target the clock, we need to append some nodes to it, one for each digit. We’ll have to add 8 (hours, minutes, seconds and two colons):

function init() {
    var theClock = document.getElementById('jsClock');
    
    for ( var i = 0; i < 8; i++) {
        var digit = document.createElement('div');
        theClock.appendChild(digit);
    }
}

Here we create a DIV element, then append (or add) it to the clock div. But what about the colon digits? Let’s flag those in the same loop:

var digits = [];

function init() {
    var theClock = document.getElementById('jsClock');

    for ( var i = 0; i < 8; i++) {
        var digit = document.createElement('div');
        
        //either flag as colon or add to digits array
        if (i == 2 || i == 5) digit.className = 'digit-colon';
        else digits.push(digit);
        
        theClock.appendChild(digit);
    }
}

Now we’ve added the class name ‘digit-colon’ where appropriate. Additionally, each of the other, non-colon digits has been added to an array of digits. This is for easy access later (we have to define the digits array outside of the init() function to ensure it is publicly accessible).

Also please note that the digit nodes exist in the DOM immediately after we use the createElement() method. Thus we are able to do these things before actually appending the digits to the clock.

The core clock function

Finally, all the pieces are in place to write to write our clock function.

We first take the time string we generated previously, and set it to a variable as an integer. Then we add to this integer every second using setInterval():

var d = new Date();
var timeStr = d.getHours() + padZeros(d.getMinutes(), 2) + padZeros(d.getSeconds(), 2);

var currTime = parseInt(timeStr);

function tictoc() {
    currTime++;
}

var clockInterval = setInterval("tictoc()", 1000);

This stores the current time in a variable that changes every second. However, this is on the base 10 decimal scale, so each of the numbers go up to 99, when they should only go up to 23 for the hours and 59 for the minutes and seconds. Let’s build in some logic to handle that:

function tictoc() {
    currTime++;
    
    timeStr = padZeros(currTime, 6);
    
    // if seconds equal to 60
    if ( timeStr.substr(4,2) == '60' ) {
        currTime += 40;
        timeStr = padZeros(currTime, 6);
    }
    
    // if minutes equal to 60
    if ( timeStr.substr(2,2) == '60' ) {
        currTime += 4000;
        timeStr = padZeros(currTime, 6);
    }
    
    // if hours equal to 24
    if ( timeStr.substr(0,2) == '24' ) {
        currTime -= 240000;
        timeStr = padZeros(currTime, 6);
    }

}

A few things happened here. First, we used the padZeros() function again to set the currTime to 6 digits. If the last two are 60, we add 40 to the currTime (thus making it 00 seconds and adding 1 to the minutes) and the timeStr is reset. The same occurs for the minutes, and if the hours are 24, they are set back to 00 (we’re on military time).

Now to complete the function, we can use the timeStr to change the clock digits in the DOM:

var d = new Date();
var timeStr = d.getHours() + padZeros(d.getMinutes(), 2) + padZeros(d.getSeconds(), 2);

var currTime = parseInt(timeStr);

function tictoc() {

    currTime++;
    
    timeStr = padZeros(currTime, 6);
    
    // if seconds equal to 60
    if ( timeStr.substr(4,2) == '60' ) {
        currTime += 40;
        timeStr = padZeros(currTime, 6);
    }
    
    // if minutes equal to 60
    if ( timeStr.substr(2,2) == '60' ) {
        currTime += 4000;
        timeStr = padZeros(currTime, 6);
    }
    
    // if hours equal to 24
    if ( timeStr.substr(0,2) == '24' ) {
        currTime -= 240000;
        timeStr = padZeros(currTime, 6);
    }

    
    // change classNames
    for ( var i = 0; i < 6; i++) {
        digits[i].className = 'digit-' + timeStr.charAt(i);
    }

}

var digits = [];

function init() {
    var theClock = document.getElementById('jsClock');

    for ( var i = 0; i < 8; i++) {
        var digit = document.createElement('div');
        
        //either flag as colon or add to digits array
        if (i == 2 || i == 5) digit.className = 'digit-colon';
        else digits.push(digit);
        
        theClock.appendChild(digit);
    }
    
    var clockInterval = setInterval("tictoc()", 1000);
}

Here we use a for() loop to adjust the class name of each of the six digits we defined earlier as the digits array.

Finally, we have to move the setInterval for the clock to the end of the init() function, to ensure it fires after the clock digits have been created.

Optimizing the clock function

There are a few things we can do to optimize the clock function. First, since the minutes only change when the seconds reach 60 and turn over, we only need to check if the minutes turn over then:

function tictoc() {

    currTime++;
    
    timeStr = padZeros(currTime, 6);
    
    // if seconds equal to 60
    if ( timeStr.substr(4,2) == '60' ) {
        currTime += 40;
        timeStr = padZeros(currTime, 6);
    
        // if minutes equal to 60
        if ( timeStr.substr(2,2) == '60' ) {
            currTime += 4000;
            timeStr = padZeros(currTime, 6);
        
            // if hours equal to 24
            if ( timeStr.substr(0,2) == '24' ) {
                currTime -= 240000;
                timeStr = padZeros(currTime, 6);
            }
    }
    
    // change classNames
    for ( var i = 0; i < 6; i++) {
        digits[i].className = 'digit-' + timeStr.charAt(i);
    }

}

Now the clock should be running a bit smoother, but let’s improve it further. Although every second, the clock updates every digit, most times we only need to change the seconds digits. We only need to change the minutes, for instance, when the seconds turn over:

function tictoc() {

    currTime++;
    
    timeStr = padZeros(currTime, 6);
    
    var startChange = 4;
    
    // if seconds equal to 60
    if ( timeStr.substr(4,2) == '60' ) {
        currTime += 40;
        timeStr = padZeros(currTime, 6);
        
        startChange = 2;
    
        // if minutes equal to 60
        if ( timeStr.substr(2,2) == '60' ) {
            currTime += 4000;
            timeStr = padZeros(currTime, 6);
            
            startChange = 0;
        
            // if hours equal to 24
            if ( timeStr.substr(0,2) == '24' ) {
                currTime -= 240000;
                timeStr = padZeros(currTime, 6);
            }
        }
    }
    
    // change classNames
    for ( var i = startChange; i < 6; i++) {
        digits[i].className = 'digit-' + timeStr.charAt(i);
    }

}

We accomplished this in a fairly clever way. Since we are already looping through the digits, we start by flagging the default starting point as 4 in the digits array (the 5th digit). Then if the seconds roll over, we set this back to 2, and if the minutes roll over we set it to 0.

Now the only problem is that when the clock loads, it’s only flagged to change the seconds digits (usually). In order to load the entire time, let’s put the digit changing loop into a function so we can call it on page load as well:

function changeDigits( startChange, timeStr ) {
    for ( var i = startChange; i < 6; i++) {
        digits[i].className = 'digit-' + timeStr.charAt(i);
    }
}

Now on page load we can just pass this function the time string: changeDigits( 0 , timeStr)

Our clock Javascript is pretty optimized, but there are many other ways to improve it, and I encourage you to seek them out and post here. For starters, try wrapping all the Javascript up we wrote here in a single object, it will make implementing the clock easier with less conflicts.

Be Sociable, Share!

Tags: , , , ,

One Response to “Make a Javascript Clock”

  1. Selva Comments Says:

    very useful Tutorial …Thanks

Leave a Comment