How to Create a Countdown Timer in JavaScript

I'm now signed up for two ColdFusion conferences this year: cf.Objective() in early May and CFUnited in late June. While I was looking at the promotional badges for the conferences, I got the idea for making a countdown timer for each one.

I did a Google search to see if there were any countdown functions already out there I could use and simply plug the start date of the conference, but while I found some example timers I couldn't quite find what I wanted, so I decided to roll my own.

I started by creating the function that would run every second to update the countdown and the function:

function runCountdown() {
var countDown= calculateCountdown();
updateDisplay(countDown);
window.setTimeout("runCountdown()","1000");
} //end of runCountdown function

The window.setTimout method takes two parameters, the function that should be run and the number of milliseconds from now when that function should be run. Setting the runCountdown function to call itself creates an infinite loop.

The first function called within the runCountdown function is calculateCountdown function:

function calculateCountdown() {
//The current date and time
var todaysDate= new Date();

/*The date and time of the target date in Greenwich Mean Time (year, month-1, day of month, hours in 24-hour notation, minutes, seconds, milliseconds). The "month-1" can trip you up if you're not carefully. So, for example, May is 4.*/
var targetDate= new Date(2008,7,25,13,0,0,0);

/*The getTimezoneOffset function returns the number of minutes west of GMT the browser is. For example, a browser in the New York EST timezone would be 300 minutes off of GMT. NOTE: does not factor in Daylight Saving Time.*/
var timezoneOffset= (todaysDate.getTimezoneOffset()*60)*1000;

/*Factor in the time zone of the web browser before determine the time between now and the conference start time.*/
var timeDifference= (targetDate-timezoneOffset)-todaysDate;

//Now calculate the days, hours, minutes, and seconds from the time difference
var countDown= new Array(4);
countDown[0]= Math.floor((((timeDifference/1000)/60)/60)/24);
countDown[1]= Math.floor((((timeDifference/1000)/60)/60) % 24);
countDown[2]= Math.floor(((timeDifference/1000)/60) % 60);
countDown[3]= Math.floor((timeDifference/1000) % 60);
   
//Output the result
return countDown;         
} //end of the calculateCountdown function

As mentioned in the code comments, the first two statements define today's date (as perceived by the browser) and the date of the target event. The JavaScript date object numbers the months in the year as 0 (January) through 11 (December), so you have to be careful when setting the month parameter for your new Date object.

Because the current date and time is determined by the user's web browser, and the user could be in any time zone around the world, you have to account for the time zone difference. To do this, first make sure that the hour value of your targetDate Date object is set to the hour it would be in Greenwich when the conference starts (so if the event starts at 8am Eastern Standard Time, it would be 1pm (13:00 hours) in Greenwich when the event started). Then you would use the built-in JavaScript function getTimezoneOffset() on your todaysDate Date object to get the number of minutes west of Greenwich the user is located and convert that number to milliseconds.

Once that's done, you can subtract the timezoneOffset value from the value of the targetDate (in milliseconds), and then subtract from that result the value of todaysDate (also in milliseconds) to get the difference between the current date and time and the target date and time.

(As noted in the comments, this doesn't take Daylight Saving Time into account, so if the current hour is affected by DST but the target date falls outside of DST, the countdown will be off by an hour, but there's no easy or completely accurate way to determine if DST comes into play for a particular user).

Once you have the difference between the two Date objects, you can break down that difference into days, hours, minutes, and seconds. First you divide the time difference by the number of milliseconds in a second, the number of seconds in a minute, the number of minutes in an hour, and the number of hours in a day, and use the "floor" method of the Math object to round the result down to the nearest complete hour:

countDown[0]= Math.floor((((timeDifference/1000)/60)/60)/24);

Then you can get the number of hours by finding the modulus (the remainder) returned when trying to find the number of days:

countDown[1]= Math.floor((((timeDifference/1000)/60)/60) % 24);

You then perform similar calculations to determine the leftover minutes and leftover seconds:

countDown[2]= Math.floor(((timeDifference/1000)/60) % 60);
countDown[3]= Math.floor((timeDifference/1000) % 60);

Now you have the numeric values for your countdown timer, returned to the runCountdown function as an array called countDown. The next step is to update the timer display with these values, and that is handled by the updateDisplay function:

function updateDisplay(countDown) {
jsChangeNodeText("daysSpan",countDown[0]);
jsChangeNodeText("hoursSpan",countDown[1]);
jsChangeNodeText("minutesSpan",countDown[2]);
jsChangeNodeText("secondsSpan",countDown[3]);
} //end of updateDisplay function    
function jsChangeNodeText(id,text) {
//Get element
node_element= document.getElementById(id);
      
//Update the text node within the element, forking depending on browser
if (typeof node_element.innerText != "undefined")
{
//IE browser, so use innerText to update
node_element.innerText= text;
}
else
{
//Use childNodes reference
node_element.childNodes[0].nodeValue= text;
}
} //end of jsChangeNodeText

Each line of the updateDisplay function passes the id of the HTML element to be updated and the value that should be displayed in that element to the jsChangeNodeText function. The jsChangeNodeText function is a function I wrote a while back (way before I started to use the jQuery JavaScript library) for updating the text within HTML elements like <span> elements, <div> blocks, etc.

The end result: a countdown timer that calculates the difference between the current date and time and the date and time of some event and updates that difference every second.

As it turned out, I think I spent more time trying to format the timer displays so that they looked like they were part of the promotional badges than I did on the JavaScript programming itself (see the related post). But it was still a fun little project, and now I can look at the badges in my sidebar and be reminded that it won't be long until I'll be hanging out with my fellow ColdFusion developers.

Related Blog Entries

Comments
Love the blog - but noticed that you never posted the wrapping HTML code to display the timer. Any chance we might get that?
# Posted By Iggy | 7/24/08 9:25 AM
@Iggy: There's nothing all that special about the HTML and CSS used to lay out the badge, and having learned a few CSS tricks since I wrote the badges, I probably wouldn't do it the same way if I had to do it again.
# Posted By Brian Swartzfager | 7/25/08 7:44 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.