Human Readable Time solution code explanation

The solution code for Human Readable Time challenge on codewars is:

 function secondsToString(seconds)
{
var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
return numhours + ":" + numminutes + ":" + numseconds + ":";
}

I don’t understand this code, especially these three variables:

numhours, numminutes, numseconds

So I need explanation for this solution code.

This link the CHALLENGE:

Maybe these descriptions will help:

Math.floor and Remainder operator

That does not pass the challenge.

Anyway it’s far more complicated than necessary. For example to get hours all you need is:
Math.floor(seconds/3600)

where exactly are you getting this “solution” code?

it doesnt solve the challenge.
it doesnt even use the right function name.

It looks like you stole the code from https://newbedev.com/convert-time-interval-given-in-seconds-into-more-human-readable-form , didnt understand it, and have come here pretending to have gotten a solution.

No I didn’t stole the code from this website !!!

I change the function name then I submitted the challenge.
This code isn’t the solution code. I thought that !

And my last solution is:

const humanReadable = (seconds) => {
  let hours = Math.floor(seconds / 3600);
  let minutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
  let numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
  if (hours < 10) {
    hours = "0" + hours
  } 
  if (minutes < 10) {
    minutes = "0" + minutes
  }
  if (numseconds < 10) {
    numseconds = "0" + numseconds
  }
  return hours + ":" + minutes + ":" + seconds;
}

Try:

let minutes = Math.floor(seconds / 60 % 60));
let numseconds = seconds % 60;

didnt answer the question of where you did get it…

your answer copies and pastes those formulas… ‘your’ last one is just the first code with Archibald’s first correction in place without being able to construct the missing lines. You’ve shown no learning there.

Now hes given you every line you need to fix the other site’s code. But lets try one more time before you simply take Archibald’s code and run away again: why does this code work? What would you do if asked to give the number of days?

Of course, from StackOverflow. It’s okay for any developer to do that !!!
But I don’t copy and paste directly. I take the code to understand, then use it.

So I pasted the code here to understand this code and learn something new. You accused me of stealing that code, and that’s totally unacceptable. We are here to get feedback and learn.

So what have you learnt?

I tried that.
For example, If the seconds are 359999 and I want to turn to minutes, I divide by 60, the result 5999.983333333334. But I want the minutes that come after hours, so I use % operator and then the result is 59.983333333333576. Finally, I use Math.floor or parseInt to have a whole number.

And I tried.
I used to many inputs like: humanReadable(359999), (humanReadable(3601) and more, with using also console.log().

See, thats more like it.

If you’ve absorbed the idea of what the divisor/modulo operator does, you can generate your own answer to the coding challenge, which is what it’s designed to do.

To go back to your original post of not understanding a line like this:

We need to go back to the original source of the code.

 function secondsToString(seconds)
{
var numyears = Math.floor(seconds / 31536000);
var numdays = Math.floor((seconds % 31536000) / 86400); 
var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
return numyears + " years " +  numdays + " days " + numhours + " hours " + numminutes + " minutes " + numseconds + " seconds";

}

Note that this code was originally developed to look for the number of YEARS first (which is where 31536000 comes from - number of seconds in a year), and was not bound by constraints such as “it will be less than 100 hours”.

Archibald is correct in that the later lines can be simplified - but only because every larger value’s modulo is a multiple of the smaller one.

X % 3600 % 60 is redundant; 3600 is a multiple of 60, so you can just say X % 60 and get the answer immediately.

Also, as all things with time goes, finding the ‘number of years’ by doing simple math is inevitably going to go wrong - because you have to account for things like leap years. Not every year is 3156000 seconds long.

As you have three “if” statements there all doing essentially the same thing, you could consider calling a function three times to format the numbers to be two digits. Here is the code I wrote earlier to solve the challenge (which also more explicitly creates strings representing the numbers):

function humanReadable(seconds) {
  let hrs = format(Math.floor(seconds / 3600));
  let mins = format(Math.floor(seconds / 60 % 60));
  let secs = format(seconds % 60);
  return( hrs + ":" + mins + ":" + secs );
}
function format(x) {
  let s = x.toString();
  if (s.length < 2) s = "0" + s;
  return s;
}

There are enthusiasts in this forum who like to have numerous functions, even if some functions are only two or three lines long. My own preference tends to be to keep a function such as this together and not to call any other small functions. This way the code can be more readable and it saves you having to find elsewhere in your code the subfunctions being called.

Both of us should have added comments to our code :grinning:.

The challenge is about you have seconds any number of seconds, and you want to turn seconds to human-readable time.
When humanReadable(3601), the output is: 01:00:01

well no, you have seconds <= 359999, but thats the thrust of the challenge, yes.

What I was pointing out is that the code that you originally quoted was designed not for this challenge, but for a general 'how do i convert seconds to years/days/hours/minutes/seconds, and that that code will have problems with the number of seconds being more than 4 years.

You are right. So, I wrote another code:

function addIFlessThanTen (num) {
  return num < 10 ? "0" + num : num
}
function humanReadable(seconds) {
  let hours = addIFlessThanTen(parseInt(seconds / 3600))
  let minutes = addIFlessThanTen(parseInt(seconds / 60 % 60))
  let secondsNum = addIFlessThanTen(parseInt(seconds % 60))
  return `${hours}:${minutes}:${secondsNum}`;
}

Or this code from @Archibald :

Incidentally, you can also avoid reinventing the wheel - Javascript’s had this problem so often that they incorporated it into the string object.

String.prototype.padStart() - JavaScript | MDN (mozilla.org)

1 Like