Navigating between two intervals in JavaScript requires following a few simple steps

I have created a digital clock with a button that switches the format between AM/PM system and 24-hour system. However, I am facing an issue where both formats are running simultaneously, causing the clocks to change every second.

Despite trying various solutions, I am unable to resolve this issue.

const clock = document.querySelector('.clock');
const changeFormatButton = document.querySelector('.button-formatChange');

changeFormatButton.addEventListener('click', change);

let count = 0;
change();

function showTime24(){

    let date = new Date();
    let hours = date.getHours();
    let minutes = date.getMinutes();
    let seconds = date.getSeconds();

    hours = addZeros(hours);
    minutes = addZeros(minutes);
    seconds = addZeros(seconds);

    clock.innerHTML = `${hours} : ${minutes} : ${seconds}`;

}

function showTime12(){

    let date = new Date();
    let hours = date.getHours();
    let minutes = date.getMinutes();
    let seconds = date.getSeconds();
    let format = changeAMPM(hours);
    hours = changeFormat(hours);

    hours = addZeros(hours);
    minutes = addZeros(minutes);
    seconds = addZeros(seconds);

    clock.innerHTML = `${hours} : ${minutes} : ${seconds} ${format}`;
}

function changeFormat(time){
    if(time > 12){
        time -= 12;
    }
    if(time === 0){
        time = 12;
    }
    return time;
}

function addZeros(time){
    if(time < 10){
        time = '0' + time;
    }
    return time;
}

function changeAMPM(time){
    if(time < 12){
        format = 'AM';
    }
    if(12 < time < 24){
        format = 'PM';
    }
    return format;
}

function change(){
    count++
    let a = setInterval(showTime12, 0);
    let b = setInterval(showTime24, 0);

    if(count % 2 == 0){
        clearInterval(a);
    }
    else if(count % 2 == 0){
        clearInterval(b);
    }
    console.log(count);
}

Both clocks are running simultaneously and clicking the button only adds to the confusion.

https://i.stack.imgur.com/sBxhX.gif

Answer №1

There are two key issues to address in this code:

1- Within the change function, the new intervals are being set without clearing the previous ones, resulting in overlap between the old and new intervals.

To resolve this, it is essential to clear the current interval before assigning new ones (consider utilizing a single interval variable).

2- The conditions within the if and else if statements are identical (count % 2 == 0), meaning that the else block will never be executed!

var interval = setInterval(showTime12, 0); //default format

function change(){
    count++;
    clearInterval(interval); //clear the previous interval

    if(count % 2 == 0){
        interval = setInterval(showTime12, 0);
    }
    else {
        setInterval(showTime24, 0);
    }
    console.log(count);
}

Edit: Proposed Improved Approach

As suggested by multiple users, adopting a more streamlined solution involves utilizing a single interval and altering a minor variable. This revised approach entails:

var mode = '12'; //assuming the default format is 12

function change(){
    mode = (mode == '12') ? '24' : '12';
}

function run() {
    action = (mode == '12') ? showTime12() : showTime24();
}

var interval = setInterval(run, 0); //default format

Answer №2

The provided code contains unnecessary redundancies that can be streamlined for better efficiency. It's important to address the dead branch within the logic.

if(count % 2 == 0){
    clearInterval(a);
}
else if(count % 2 == 0){ // unreachable!
    clearInterval(b);
}

To optimize this code, it is advisable to rethink the implementation of intervals and consider using a single interval with conditional operations instead. Currently, the local scope of let a = ... causes the previous interval to be lost without proper clearance after change ends.

An improved design would involve running one interval continuously and incorporating conditional tasks within it to enhance functionality.

Furthermore, replacing setInterval(fn, 1000) with requestAnimationFrame is recommended for smoother execution of constantly updating functions while avoiding skipped seconds in the process.

The code also exhibits signs of repetitive patterns, especially within showTime12 and showTime24, which are almost identical. Inlining most of the helper functions would improve code readability without sacrificing clarity.

For a functional example:

const clock = document.querySelector(".clock");
const changeFormatButton = document.querySelector(".change-format");

let militaryTime = false;
changeFormatButton.addEventListener("click", e => {
  militaryTime = !militaryTime;
});

(function showTime() {
  requestAnimationFrame(showTime);
  const date = new Date();
  let amPm = "";
  let hours = date.getHours();
  
  if (!militaryTime) {
    amPm = hours < 12 ? " AM" : " PM";
    hours = hours % 12 || 12;
  }
  
  clock.innerText = `${hours} : ${date.getMinutes()} : ${date.getSeconds()}`
                    .replace(/\d+/g, m => m.padStart(2, "0")) + amPm;
})();
<div class="clock"></div>
<button class="change-format">change format</button>

Answer №3

function updateCounter(){
    count++
    function getTimeFormat(){
        let time;
        if(count % 2 === 0){
        time = showTime12();
        }
        else if(count % 2 === 1){
        time = showTime24();
        }
        return time;
    }
    setInterval(getTimeFormat, 0);
}

Huge shoutout to @ggorlen for helping me out!

I decided to create a new function inside the updateCounter function and set that as the parameter for setInterval :)

One of the benefits of being a beginner is learning from your mistakes...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with React testing-library: Why is the file upload empty when testing a PDF file?

While testing file upload with react-testing-library, I encountered an issue where the log indicated that the file was empty (even though it worked in the browser). After researching various docs and bugs, I discovered that since tests run on Node.js, the ...

Creating webpages dynamically by utilizing Javascript

I need assistance with a task involving a list of elements that allows users to print only the clicked element, rather than the entire page. The elements are structured as follows: <div class="element" id="#element1">Element 1</div> <div cl ...

Display a division upon choosing an option

I am working on a project that involves a selection menu in the form of a drop-down list. <select> <option id="one" value="something">Car</option> <option id="two" value="anything">Plane</option> </select> Also, I ...

Issues with React Native imports not functioning properly following recent upgrade

Hey there, I’ve been tasked with updating an old React-Native iOS project from version 0.25.1 to 0.48.0. However, I’m encountering several compiler issues and struggling to navigate through the code updates. The project includes an index.ios.js file s ...

clearing all input fields upon submission in React Native

I need help resolving an error that occurs when I try to clear text input fields on a button press. Instead of clearing the fields, it throws an undefined error because I am trying to set the value as {this.state.inputTextValue} and then clear it using set ...

What is the best way to navigate from a button in NextJS to another page that I have built within the same application?

As I work on developing a website for a pet rescue charity using Next.js, I am facing an issue with getting my button or link to function correctly. Every time I try to navigate to another page within my Next.js app, I encounter a 404 error stating "This p ...

Using React Material UI icon within an auto complete feature

https://i.stack.imgur.com/W3CmF.png I am struggling to incorporate the target icon into the autoComplete component. After reviewing the documentation, I have been unable to find a solution. In TextInput, a similar outcome can be achieved by implementing ...

Error: The program encountered a type error while trying to access the '0' property of an undefined or null reference

I am a beginner in the world of coding and I am currently working on creating an application that allows users to add items to their order. My goal is to have the quantity of an item increase when it is selected multiple times, rather than listing the same ...

Tips for transferring information from one php page to another php page via ajax

I am attempting to retrieve data from one PHP page and transfer it to another page through the use of Ajax. JavaScript : $.ajax({ url: "action.php", success: function(data){ $.ajax({ url: "data.php?id=data" ...

Tips for incorporating a multimedia HTML/JavaScript application within C++ programming

I possess the source code for a JavaScript/HTML5 application that operates on the client-side and manages the transmission/reception of audio and video data streams to/from a server. My objective is to develop a C++ application that fully integrates the c ...

Using DraftJS to swap text while preserving formatting

Currently, I am implementing Draftjs with draft-js-plugins-editor and utilizing two plugins: draft-js-mathjax-plugin and draft-js-mention-plugin My goal is to replace all mentions with their corresponding values when the user uses '@' to mention ...

Check to see if modifying the HTML using jQuery results in any errors

Although it may sound straightforward, let me clarify. I am utilizing ajax calls to update the content of the body and I aim to trigger an alert if the updating process fails on the client side, specifically after receiving a response from ajax in case of ...

Issues with Opera displaying specific characters when using webfonts

Perhaps it's not supposed to work this way, but hear me out. I'm utilizing Google Web Fonts and adding the PT Sans font like this: <link href="https://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" ty ...

Displaying the outcome of an HTML form submission on the current page

Within the navigation bar, I have included the following form code: <form id="form"> <p> <label for="textarea"></label> <textarea name="textarea" id="textarea" cols="100" rows="5"> ...

JavaScript Comparison of Numerical String Syntax

I created an HTML function to determine the maximum number, but it is returning incorrect results. Could someone please point out what I am doing wrong? Thank you! The code is as follows: <!DOCTYPE html> <html> <head> <meta charset=& ...

What causes the toggle effect in my jQuery onclick function to alternate between on and off when the initialization is repeated multiple times?

I am facing an issue with my website where icons/buttons trigger a menu when clicked. I need to load more data by adding more buttons, so I tried re-initializing the existing buttons using a jQuery onclick function whenever the number of buttons changes. ...

Having difficulty retrieving the necessary information for manipulating the DOM using Express, Ajax, and Axios

When working on DOM manipulation based on AJAX calls, I've encountered an issue where the response is being displayed on my page instead of in the console.log output. This makes it difficult for me to view the data and determine what needs to be inser ...

What is the best way to create a mapping function in JavaScript/TypeScript that accepts multiple dynamic variables as parameters?

Explaining my current situation might be a bit challenging. Essentially, I'm utilizing AWS Dynamodb to execute queries and aiming to present them in a chart using NGX-Charts in Angular4. The data that needs to appear in the chart should follow this fo ...

Typescript: Why Lines Are Not Rendering on Canvas When Using a For-Loop

What started out as a fun project to create a graphing utility quickly turned into a serious endeavor... My goal was simple - to create a line graph. Despite my efforts, attempting to use a for-loop in my TypeScript project resulted in no output. In the ...

Tips for incorporating dynamic content into React Material UI expansion panels while maintaining the ability to have only one tab active at a time

I'm working on a project using WebGL and React where I generate a list of users from mock data upon clicking. To display this content in an accordion format, I decided to use Material UI's expansion panel due to my positive past experience with ...