1

I am using js to render a 12 hour digital clock that continuously updates. However, the code I found online left me with a 24 hour clock and the wrong am/pm output. Right now it shows 13:33 am. I have tried out other snippets of code here and there, some jquery examples, but nothing worked and a lot of css already went into this one. How would I convert this to a properly functioning 12 hour clock? Thanks!

$(document).ready(function() {

  setInterval(function() {
    // Create a newDate() object and extract the hours of the current time on the visitor's
    var hours = new Date().getHours();
    // Add a leading zero to the hours value
    $(".hours").html((hours < 10 ? "0" : "") + hours);
  }, 1000);
});

setInterval(function() {
  // Create a newDate() object and extract the minutes of the current time on the visitor's
  var minutes = new Date().getMinutes();
  // Add a leading zero to the minutes value
  $(".min").html((minutes < 10 ? "0" : "") + minutes);
}, 1000);

setInterval(function() {
  var time = new Date().getHours();
  var time = (time + 24 - 2) % 24;
  var mid = 'am';
  if (time == 0) { //At 00 hours we need to show 12 am
    hours = 12;
  } else if (time > 12) {
    time = time % 12;
    mid = 'pm';
  }
  $(".ap").html(mid);
});
ul {
  list-style: none;
}

li {
  display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="clock">
  <ul>
    <li class="hours"></li>
    <li class="point">:</li>
    <li class="min"></li>
    <li class="ap"></li>
  </ul>
</div>
Baezid Mostafa
  • 2,480
  • 2
  • 11
  • 24
Benjamin Morrison
  • 773
  • 2
  • 8
  • 21

2 Answers2

3

First problem is with this line:

var hours = new Date().getHours();

It takes the current hours which will be from 0 to 23. For example:

var hours = new Date('2020-01-01 16:00:00').getHours();

console.log(hours);

You need to convert this to 1-12 range by using the modulo operator:

var hours = new Date('2020-01-01 16:00:00').getHours() % 12;

console.log(hours);

The only thing needed is to make sure that midnight is shown as 12:

var hours = new Date('2020-01-01 00:00:00').getHours() % 12;

if (hours === 0) {
  hours = 12;
}

console.log(hours);

Second problem is when determining AM or PM.

var time = (time + 24 - 2) % 24;

is wrong the -2 offset makes any hour incorrect:

var time = 16;

time = (time + 24 - 2) % 24;

console.log(time);

var time = 1;

time = (time + 24 - 2) % 24;

console.log(time);

Next, adding 24 to the hours is useless. Finally, the modulo 24 operation is unneeded once the +24 offset is removed. In effect the entire line throws off all calculations. You need to remove it.

There is other logic that tries to properly format the hours but it's misplaced, since this code never sets the hours - that's already set elesewhere. This code only sets the AM/PM.

Lastly, the third setInterval is missing an interval value. Technically, that will still work but it will run the function very often. Based on the other setInterval invocations, it seems the intent is to have a delay of 1000 (it's in milliseconds).

When all of this is done, here is what the code looks like:

$(document).ready(function() {

  setInterval(function() {
    // Create a newDate() object and extract the hours of the current time on the visitor's
    var hours = new Date().getHours() % 12;
    
    //At 00 hours we need to show 12 am
    if (hours === 0) {
      hours = 12
    }
    
    // Add a leading zero to the hours value
    $(".hours").html((hours < 10 ? "0" : "") + hours);
  }, 1000);
});

setInterval(function() {
  // Create a newDate() object and extract the minutes of the current time on the visitor's
  var minutes = new Date().getMinutes();
  // Add a leading zero to the minutes value
  $(".min").html((minutes < 10 ? "0" : "") + minutes);
}, 1000);

setInterval(function() {
  var time = new Date().getHours();
  
  var mid = 'am';
  
  if (time > 12) {
    mid = 'pm';
  }
  $(".ap").html(mid);
}, 1000);
li {
 display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="clock">
  <ul>
    <li class="hours"></li>
    <li class="point">:</li>
    <li class="min"></li>
    <li class="ap"></li>
  </ul>
</div>
VLAZ
  • 18,437
  • 8
  • 35
  • 54
0

Here's a function that'll be helpful. It takes military hours and minutes in the form of numbers and returns an array of 12-hour time components (the hour, the minutes, and the am/pm).

function get12HourTimeComponents(hours, minutes) {
  minutes = (minutes < 10 ? "0" : "") + minutes;
  if (hours % 12 == 0) return [12, minutes, hours == 12 ? "pm" : "am"];
  return [hours % 12, minutes, hours < 12 ? "am" : "pm"];
}

console.log(get12HourTimeComponents(15, 23));

The first line adds a leading 0 to minutes if needed. The second line handles cases where the hour is 0 or 12 specifically (because they don't work well with the % operator in the third line). The third line returns an array for all other cases while converting hours to 12-hour format and checking if hours indicate "am" or "pm". To implement this in your code, you'd do this:

function get12HourTimeComponents(hours, minutes) {
  minutes = (minutes < 10 ? "0" : "") + minutes;
  if (hours % 12 == 0) return [12, minutes, hours == 12 ? "pm" : "am"];
  return [hours % 12, minutes, hours < 12 ? "am" : "pm"];
}

function showTime() {
  var date = new Date();
  var twelveHourTimeComponents = get12HourTimeComponents(date.getHours(), date.getMinutes());

  $(".hours").html(twelveHourTimeComponents[0]);
  $(".min").html(twelveHourTimeComponents[1]);
  $(".ap").html(twelveHourTimeComponents[2]);
}
$(document).ready(function() {
  showTime(); //show time immediately when page loads
  setInterval(showTime, 1000); //and every second after that
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class="clock">
  <ul>
    <li class="hours"></li>
    <li class="point">:</li>
    <li class="min"></li>
    <li class="ap"></li>
  </ul>
</div>

I'm assuming you have your own CSS to style this, so I left that alone. You'll notice that I got rid of a bunch of intervals. You only need the one. You can update everything once per second with a single interval. If this is not enough explanation and you have questions, please let me know by leaving a comment.

Aaron Plocharczyk
  • 2,403
  • 2
  • 3
  • 13