NOTE: As of July 12, 2009, this blog has been discontinued and replaced by the new Thought Delimited blog. All of the entries in this blog can be found there, along with new posts.

How to Create a Countdown Timer in JavaScript


Update (2/7/2009): Since a couple of commenters asked for the complete code or a working example, I went back and cleaned up the code a bit to create a working demo that folks can view and download the source code for. You can find the demo at this URL: http://www.swartzfager.org/blog/demoFiles/countdownTimer.html

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
Just wanted to say thanks for saving me from throwing my computer out the window. I'm pretty new to programming in general and have only tried a couple javascript projects. I spent atleast 8 to 10 hours trying to make my own counter and about 4 to 6 more going over other peoples tutorials online and couldn't ever get past scope issues when using setInterval. Its funny to me that scope seemed to be the big issue for everyone but your article was the easiest to understand and to get to work and it never mentioned scope once. Thanks again.
# Posted By timB | 1/20/09 4:26 PM
@timB: Thanks for the comment. I'm always glad to hear it when my posts or plugins have helped someone.
# Posted By Brian Swartzfager | 1/20/09 9:23 PM
Hi Brian,

Thanks for the info on creating a countdown timer, this looks very useful!

But, for use jscript newbies, can you post the code that is necessary to get this to work? What/how do we setup our page to call the countdown timer function? I've tried a number of things and have had no luck.

Thanks,
Steven
# Posted By Steven | 1/27/09 2:53 PM
I agree with a few other comments - you provide a lot of great information and detail but do not illustrate the last step - how to use all the functions to produce a working countdown timer on a page. Can you do that and/or link to a page with the timer? Thanks for the great post.
# Posted By foneguy | 2/3/09 9:59 AM
@Steven, @foneguy: I'll try to get the full code posted (or in download form) before the end of the coming weekend. I've just been really busy with work lately and this keeps slipping my mind.
# Posted By Brian Swartzfager | 2/3/09 10:16 AM
I've put up a working demo of the script at:

http://www.swartzfager.org/blog/demoFiles/countdow...

You can use the "View Source" option on your browser to view/copy/download the code.
# Posted By Brian Swartzfager | 2/7/09 4:23 PM
Perfect - thanks! FYI - I used label id="daysCounter" etc. to format the output and it looks great. Thanks again
# Posted By foneguy | 2/9/09 11:47 AM
The CountdownTimer is a great script and I have it working - thank you.
Is there any way to get more than one working on a page?
Thank you
Jack
# Posted By Jack | 3/10/09 7:19 AM
@Jack: You'd have to figure out the best way to store the additional event dates and the countdown values and rework the functions to accept the particular event you're counting down to as a parameter, but it should be possible.
# Posted By Brian Swartzfager | 3/10/09 7:33 AM
You can also mix it with php and make it customizable and update it to show monthes and years like here http://free-countdown.co.nr/
# Posted By myincome | 7/8/09 12:20 PM
very cool & good tutorial, thank you very much for sharing.

Can I share this tutorial on my <a href="http://www.javascriptbank.com/">JavaScript library</a>?


Awaiting your response. Thank
# Posted By JavaScript Countdown Timer | 10/4/09 12:20 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.