Newbie: Please explain this line of code and how it works

I have this function to format and display the time which I found on the net.

function DateTime() {
curHour = objToday.getHours() > 12 ? objToday.getHours() - 12 : (objToday.getHours() < 10 ? "0" + objToday.getHours() : objToday.getHours()),
	curMinute = objToday.getMinutes() < 10 ? "0" + objToday.getMinutes() : objToday.getMinutes(),
	curMeridiem = objToday.getHours() > 12 ? "PM" : "AM";
	today = + curHour + ":" + curMinute + " "+ curMeridiem;
}

At 12 AM it is displaying 0 for the hours. I fixed it by adding

if (curHour = "0") {curHour= "12"};

I am wondering if I can fix it in a more elegant way.
I see what this statement accomplishes but dont really understand it how it works.

curHour = objToday.getHours() > 12 ? objToday.getHours() - 12 : (objToday.getHours() < 10 ? "0" + objToday.getHours() :

Can someone please explain it to me (not the logic, but what all the stuff with : and ? does). Could this statement be modified so I can remove my if statement?

Some people get too cute about compacting their code, for it then becomes too difficult to understand.

There is an error with meridiem when the time is 12, for midday is not AM, it’s PM, all the way from 12:00 daytime.

Here is a converted version of the code, to help with understanding what it does.

function DateTime() {
  var hour = objToday.getHours();
  var minute = objToday.getMinutes();
  var meridiem = hour > 12 ? "PM" : "AM";

  if (hour > 12) {
    hour = objToday.getHours() - 12;
  } else {
    if (objToday.getHours() < 10) {
      hour = "0" + objToday.getHours();
    }
  }
  if (minute < 10) {
    minute = "0" + objToday.getMinutes();
  }
  today = + hour + ":" + minute + " "+ meridiem;
}

The proper rules for converting the time are found at What do AM and PM stand for.

Here’s how you correctly convert from 24-hour time to 12-hour time.

From 0:00 (midnight) to 0:59, add 12 hours and use am.
0:49 = 12:49 am (0:49 + 12)

From 1:00 to 11:59, just add am after the time.
11:49 = 11:49 am

From 12:00 to 12:59, just add pm after the time.
12:49 = 12:49 pm

From 13:00 to 0:00, subtract 12 hours and use pm.
13:49 = 1:49 pm (13:49 - 12)

Let’s not change what works, and use those rules in the code instead.

But first, to make sure that things keep working as they should, I’ll use some tests to help check that my changes work, and that the code continues to work throughout the changes.

No complex testing harness needs to be involved here, we can just use some console.log commands.

objToday = {
  getHours: function () {return 1;},
  getMinutes: function () {return 0;}
};
DateTime();
if (today !== "1:00 AM") {
  console.log("Expected 1:00 AM but got ", today);
}

objToday = {
  getHours: function () {return 10;},
  getMinutes: function () {return 10;}
};
DateTime();
if (today !== "10:10 AM") {
  console.log("Expected 10:10 AM but got ", today);
}

objToday = {
  getHours: function () {return 12;},
  getMinutes: function () {return 59;}
};
DateTime();
if (today !== "12:59 PM") {
  console.log("Expected 12:59 PM but got ", today);
}

The last test fails, resulting in the logged output because it gets “12:59 AM” from the original code. We’ll fix that up shortly by following the instructions.

Deleting the original code, we start with:

  var hour = objToday.getHours();
  var minute = objToday.getMinutes();
  var meridiem = "";

Following the instructions, we get the following code:

  // Details on converting from 24 hour to 12 hour from:
  // https://www.timeanddate.com/time/am-and-pm.html
  if (hour === 0) {
    hour += 12;
    meridiem = "AM";
  }
  if (hour > 0 && hour <= 11) {
    meridiem = "AM";
  }
  if (hour === 12) {
    meridiem = "PM";
  }
  if (hour >= 13) {
    hour -= 12;
    meridiem = "PM";
  }

And we just need to pad a zero in front of the minutes:

  if (minute < 10) {
    minute = "0" + minute;
  }
  today = hour + ":" + minute + " " + meridiem;

And the tests all pass with flying colors.

It’s normally not a good ideas to use global variables, so instead of using objToday, I’d have the function accept that as a function parameter, give it a more appropriate name, and return the time string from the function.

function format12Hour(date) {
  var hour = date.getHours();
  var minute = date.getMinutes();
  ...
  return hour + ":" + minute + " " + meridiem;
}

var today = format12Hour(objToday);

Here’s the full function code that it’s ended up becoming.
It’s now much more usable and stable code that you can use in every project, and it’s easy to understand it too.

function format12Hour(date) {
  var hour = date.getHours();
  var minute = date.getMinutes();
  var meridiem = "";

  // Details on converting from 24 hour to 12 hour from:
  // https://www.timeanddate.com/time/am-and-pm.html
  if (hour === 0) {
    hour += 12;
    meridiem = "AM";
  }
  if (hour > 0 && hour <= 11) {
    meridiem = "AM";
  }
  if (hour === 12) {
    meridiem = "PM";
  }
  if (hour >= 13) {
    hour -= 12;
    meridiem = "PM";
  }
  if (minute < 10) {
    minute = "0" + minute;
  }
  return hour + ":" + minute + " " + meridiem;
}
1 Like

Specifically on this point, this is referred to as the ‘ternary operator’ in some languages. It could be described as a mini if-then statement. Basically it’s:

result = (test condition) ? thing to return if condition is true : thing to return if it is not true
result = (temp < 60) ? "quite cold" : "not very cold"

which is often quicker than

if (temp < 60) result = "quite cold" else result = "not very cold"

in some code structures.

Did that fix it? By using a single = sign don’t forget you’re assigning a value here, not comparing it. Or just a typo for posting on the forum perhaps.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.