JavaScript Clocks: Fundamentals

The first thing we need when creating a clock with JavaScript is the Date object. At its core, the Date object is the number of milliseconds since the Unix epoch, January 1, 1970 at 12 AM UTC. Because this is an unwieldy number to use (it was when this page loaded) JavaScript provides a number of useful methods with the Date object.

Creating a Date object is straightforward:

let time = new Date();

Now we can start using those useful methods. Of particular interest to a clock maker are the methods getSeconds(), getMinutes(), and getHours(). These methods return an integer representing the second, minute, and hour in the user’s local time. To get the current seconds we just need to use time.getSeconds();

Now that we have access to the time, we need to do something with it. We need a place to display it. Let’s create a space for it using a <div> element with a unique id so we can access it quickly and easily from our code using document.getElementById().

Our HTML should look something like this:

<html>
  <head>
    <title>
      Clock
    </title>
  </head>
  <body>
    <div id="clock">
    </div>
  </body>
</html>

Keep in mind that depending on how we want to implement this, we can substitute our <div> for a <span> or a <p> or even a <td> element. The important thing is that we can access it from our script, and the most straightforward way to do this is with innerHTML property of a Document element.

So our script is going to look something like this:

let time = new Date();
document.getElementById("clock").innerHTML = time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds();

This is a good start and here’s what it looks like: . But now we have to solve the problem of updating our clock every second.

The standard way to run the same block of code over and over is with the setInterval() method. setInterval() needs two parameters to work, a function and a delay. The function is the code that will be run multiple times. The delay is how often that code should be run expressed in milliseconds. This is what it looks like:

let clockInterval = setInterval(function() {
  code block here;
}, delay);

Our intuition might tell us that we should set our delay to 1000 ms but because setInterval() tends to drift over time, it’s inevitable that at some point our clock will skip a second. The solution to this is to set our delay to a fraction of a second so that we’re updating our time multiple times per second. Let’s set ours to 100 ms since most people won’t notice a hiccup in time that small. Here’s our updated code:

let clockInterval = setInterval(function() {
  let time = new Date();
  document.getElementById("clock").innerHTML = time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds();
}, 100);

And here’s the result: . Cool!

But wait. Seriously, wait until the seconds turn over to 0. Clocks don’t display “0” seconds or even “5” seconds. Minutes and seconds are always displayed with two digits. How do we fix this?

Strings.

In order to insert a 0 in front of a one-digit number we need to convert it to a string first. To do that we’ll use the toString() method on our integer. It should look something like this:

time.getSeconds().toString(10);

Why did I put that “10” as a parameter to my toString() method? Because toString() can convert base-10 integers into another base before converting it into a string. In this case, we want our time to be represented in base 10. Now that we’ve got a string, it’s time to add zeroes before our one-digit number. Thankfully, there’s a method for that, too!

The padStart() method lets us define the minimum length of a string and pad the front of it with a prespecified character. Here’s how it looks:

string.padStart(minimumLength, "stringToPadWith");

We’re almost done but let’s look at one more thing. The string we’re using to display the time is getting out of hand. Just to display the current seconds we need:

time.getSeconds().toString(10).padStart(2, "0");

I recommend making our code more human readable at this point by using variables to store the seconds, minutes, and hours and using a string literal with the innerHTML property. Here’s what that looks like:

let clockInterval = setInterval(function() {
  let time = new Date();
  let hours = time.getHours().toString(10).padStart(2, "0");
  let minutes = time.getMinutes().toString(10).padStart(2, "0");
  let seconds = time.getSeconds().toString(10).padStart(2, "0");
  document.getElementById("clock").innerHTML = `${hours}:${minutes}:${seconds}`;
}, 100);

And here’s our final result: .

From here there’s a few things we can do to optimize our code such as only updating the time when it changes and updating the hours, minutes, and seconds separately. We can also declare some variables outside the scope of setInterval() so they aren’t redeclared every 100 ms.

What do you think? What did I miss? If you make a clock after reading this tutorial send me a link, I’d love to see what you come up with!

Up Next: Making an analog clock with SVG

Reference

Date
Date.prototype.getSeconds()
Date.prototype.getMinutes()
Date.prototype.getHours()
Document.getElementById()
Element.innerHTML
WindowOrWorkerGlobalScobe.setInterval()
Object.prototype.toString()
String.prototype.padStart()
Template Literals