Create a digital clock using Javascript
Tags: javascript, webdev, beginners, tutorial
Published: 2021-10-23 13:47:26

In today's tutorial we will create a digital clock that will show us the current time and it will also have a nice alarm feature. By the end of this tutorial you'll be familiar with working with the Javascript Date object, and also you'll have a minimal understanding of asynchronous code execution and the setTimeout API.

## Video tutorial
If you prefer a detailed video tutorial instead, feel free to check out the tutorial that I created on [my YouTube channel](https://www.youtube.com/channel/UCicOwFWkuMX0ddFaKCc_E5Q):

{% youtube R-bSb7xrS5s %}

## HTML
The html markup for this project is pretty simple. But before we implement that, let's add the custom font from Google that we will use in the `head` section of the HTML document. I'll also include the stylesheet that we will create later.
```html
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Orbitron&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
```
We will have a section with a class of `container` which will hold our clock. Below that we need to create an empty div, which will be used to display the current time. I give it an id of `clock`, so it will be easier to target.

```html
<section class="container">
  <div id="clock"></div>
</section>
```
Next we will add the input field, so the user will be able to select a date and time to set the alarm. The important thing here is, that the input type should be `"datetime-local"`. We'll also give it a name attribute and an onchange event handler. When the onchange event happens (so the value of the input field changes), we will fire this function `setAlarmTime(this.value)` that we will implement in our js file just in a bit. We pass `this.value` to the function which will give is the new, updated value of the input field.
```html
<input onchange="setAlarmTime(this.value)" name="alarmTime" type="datetime-local">
```
Next we have to add the control buttons. We will wrap these two buttons into a wrapper div, and give it a css class of `controls`. Inside that we'll add two buttons, "Set alarm" and "Clear alarm". Besides the css classes, we add click event hanler functions. We will create the functions: `setAlarm()` and `clearAlarm()` in javascript later.
```html
<div class="controls">
  <button onclick="setAlarm()" class="button set-alarm">Set alarm</button>
  <button onclick="clearAlarm()" class="button clear-alarm">Clear alarm</button>
</div>
```
Lastly, we have to include our javascript file at the bottom of our HTML document's body. We need to import it at the end of the document, so when our script will run, the DOM tree will be ready. (You could also include it in the head with the `defer` keyword).
```html
<script src="index.js"></script>
```
## CSS
In our `styles.css` file I'll start with clearing every browser defined paddings and margins, and also set a dark background color.
```css
body,html {
    margin: 0;
    padding: 0;
    background-color: #12181B;
}

* {
    box-sizing: border-box;
}
```
Using flexbox we'll make the container take the full viewport, and center its content.
```css
.container {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
```
For the clock we will set the font that we included earlier in the HTML, and set the desired font size. I'll also add a gradient color to the clock. To do that we will set a gradient as a background image, then we will color the font with the background gradient using the `background-clip: text` CSS rule.
```css
#clock {
    font-family: 'Orbitron', sans-serif;
    font-size: 15vw;
    background-image: linear-gradient(180deg,
        rgba(99,253,136,1) 0%,
        rgba(51,197,142,1) 50%,
        rgba(39,97,116,1) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -moz-background-clip: text;
    -webkit-text-fill-color: transparent; 
    -moz-text-fill-color: transparent;
}
```
Lastly, we make some styling to the control buttons and the wrapper div.
```css
.controls {
    margin-top: 16px;
}

.button {
    font-weight: bold;
    border-radius: 5px;
    border: none;
    color: white;
    padding: 4px 8px;
    margin-left: 4px;
    cursor: pointer;
}

.set-alarm {
    background-color: #498AFB;
}

.clear-alarm {
    background-color: #FF3860;
}
```
## Javascript
This will be the hearth of our clock application. First, we will save a reference to our clock display (the div with the `clock` id) into a display variable. We'll also set up the audio for the alarm. To do that I'll use a free alarm sound form Mixkit, feel free to use any music/sound of your choice.
We will create a new Audio object and save it to the `audio` variable. We'll also set the loop property of the audio object to true, as we want to play the sound, till the alarm is turned off manually. As you can see we have an `alarmTime` and `alarmTimeout` variables, that we initialise with null. We will use these variables to implement the alarm functionality.
```javascript
const display = document.getElementById('clock');
const audio = new Audio('https://assets.mixkit.co/sfx/preview/mixkit-alarm-digital-clock-beep-989.mp3');
audio.loop = true;
let alarmTime = null;
let alarmTimeout = null;
```
Now we'll implement the clock functionality. In the `updateTime` function we create a new Date object. As we didn't provide any parameter to it it will create an object **with the current time.** Then we create 3 variables to get the hour, minute and second values from the Date object. We can do it easily using the API of the javascript Date object.
To have a nice digital display, we'll create a function which format's the time values. It places a leading zero if the number is only one digit, otherwise it uses the number. So for example if the time value provided is `9`, it returns `09` instead.
```javascript
function formatTime(time) {
    if ( time < 10 ) {
        return '0' + time;
    }
    return time;
}
```
Lastly we have to override the `display` DOM node's innerText to represent the current time. I used string template literals here, so anything between `${}` will be replaced with the value of that variable.
```javascript
function updateTime() {
    const date = new Date();

    const hour = formatTime(date.getHours());
    const minutes = formatTime(date.getMinutes());
    const seconds = formatTime(date.getSeconds());



    display.innerText=`${hour} : ${minutes} : ${seconds}`
}
```
Now we just have to call this function every second to update the displayed time. We can do that by using the setInterval API, pass the updateTime function to it and pass 1000 (it is in ms) as it's second parameter.
```javascript
setInterval(updateTime, 1000);
```
Now we have a working clock. It's time to implement the alarm feature. The first thing is that we have to collect and save the date and time selected by the user. We already attached an `onchange` event listener in the HTMl, now we just have to implement that in javascript. We will simply get the value from the event handler and save it to the `alarmTime` variable. 
```javascript
function setAlarmTime(value) {
    alarmTime = value;
}
```
Now we should implement the `setAlarm` function. This will be responsible for setting the alarm to the desired time and play the sound. If an `alarmTime` is set we create two Date objects, one with the current time (empty parameters), and one using the user selected alarm time and date. If the time of the alarm is in the future, we will set the alarm. To calculate the time left till the alarm, we convert both dates to time in ms (this will give us pack time in ms since unix epoch, [more details here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime)) and subtract the future value from the current. This ways we know, how much ms is left till the alarm shall play. We just have to set a timeout to call the play method of the audio object. We'll also save the return result of the setTimeout function into the global `alarmTimeout` variable. We will use this reference to clear the timeout if needed.
```javascript
function setAlarm() {
    if(alarmTime) {
        const current = new Date();
        const timeToAlarm = new Date(alarmTime);

        if (timeToAlarm > current) {
            const timeout = timeToAlarm.getTime() - current.getTime();
            alarmTimeout = setTimeout(() => audio.play(), timeout);
            alert('Alarm set');
        }
    }
}
``` 
The last thing that we have to implement is the clear functionality of the alarm. We will stop the alarm sound if it already playing, and we will cancel the set alarm if it is in the future. So in our `clearAlarm` function we will call the pause method of our audio object. Then if we have a scheduled alarm (so the alarmTimeout has a value), we will use the built in `clearTimeout` function to cancel that future function call.
```javascript
function clearAlarm() {
    audio.pause();
    if (alarmTimeout) {
        clearTimeout(alarmTimeout);
        alert('Alarm cleared');
    }
}
```
The whole project is available [on GitHub.](https://github.com/javascriptacademy-stash/clock-alarm/)
## Conclusion
So this is how you can create a digital clock with alarm features in a beginner-friendly way using javascript. I think that this is an interesting project that you can build, and you also practice some fundamental javascript topics, like Dates, DOM modification and asynchronous API-s like setInterval and setTimeout.
## Where you can learn more from me?
I create education content covering web-development on several platforms, feel free to 👀 check them out.

I also create a newsletter where I share the week's or 2 week's educational content that I created. No bull💩 just educational content.

🔗 Links:
* 🍺 Support free education and [buy me a beer](https://ko-fi.com/adamnagy)
* 💬 Join our [community on Discord](https://discord.gg/GuxmcEgAjB)
* 📧 Newsletter [Subscribe here](https://www.getrevue.co/profile/dev_adamnagy)
* 🎥 YouTube [Javascript Academy](https://www.youtube.com/channel/UCicOwFWkuMX0ddFaKCc_E5Q)
* 🐦 Twitter: [@dev_adamnagy](https://twitter.com/dev_adamnagy)
* 📷 Instagram [@javascriptacademy](https://www.instagram.com/javascriptacademy/)