1
\$\begingroup\$

I need to format total number of seconds to total time in the following format: Days:Hours:Minutes:Seconds.

This is what I did:

function formatTime(totalSeconds) {
  let days = Math.floor(totalSeconds / 86400);
  let hours = Math.floor((totalSeconds - (days * 86400)) / 3600);
  let minutes = Math.floor((totalSeconds / 60) % 60);
  let seconds = totalSeconds % 60;

  days = days < 10 ? `0${days}` : days;
  hours = hours < 10 ? `0${hours}` : hours;
  minutes = minutes < 10 ? `0${minutes}` : minutes;
  seconds = seconds < 10 ? `0${seconds}` : seconds;

  let formattedString = `${days}:${hours}:${minutes}:${seconds}`;
  return formattedString;
}

console.log(formatTime(5000));

Is this OK? Or there can be a better way?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Is it OK: yes, it works.

It could be slightly cleaner.

  • I might create a const SEC_IN_HR = 3600 so that others can easily follow exactly what each equation is doing (this could be expanded to include SEC_IN_MIN and HR_IN_DAY).
  • hours is calculated correctly, but if you wanted to stick to the pattern of not referring to time variables (day, hour, etc) you could use Math.floor(totalSeconds % (SEC_IN_HR*24) / SEC_IN_HR)
  • minutes could also be re-written Math.floor(totalSeconds % SEC_IN_HR / 60)
  • because time variables are initially numbers, but end up strings, you could do the conversion earlier and then use padStart(2,'0')
  • formattedString is declared but unused, just return the formatted string, no need to declare the variable
  • you could have time variables initialized in a list [dayStr, hourStr,..], then use padStart in map, and a join(':') at the return if you wanted shorter code, though it wouldn't be clearer

const SEC_IN_HR = 3600;
function formatTime(totalSeconds) {
  const days = `${Math.floor(totalSeconds / (SEC_IN_HR*24))}`;
  const hours = `${Math.floor(totalSeconds % (SEC_IN_HR*24) / SEC_IN_HR)}`;
  const minutes = `${Math.floor(totalSeconds % SEC_IN_HR / 60)}`;
  const seconds = `${Math.floor(totalSeconds % 60)}`;

  return `${days.padStart(2,'0')}:${hours.padStart(2,'0')}:${minutes.padStart(2,'0')}:${seconds.padStart(2,'0')}`;
}

console.log(formatTime(5000));

Shorter code

const SEC_IN_HR = 3600;
function formatTime(totalSeconds) {
  let timeStr = [
    `${Math.floor(totalSeconds / (SEC_IN_HR*24))}`,
    `${Math.floor(totalSeconds % (SEC_IN_HR*24) / SEC_IN_HR)}`,
    `${Math.floor(totalSeconds % SEC_IN_HR / 60)}`,
    `${Math.floor(totalSeconds % 60)}`
  ]; // this could be on one line

  return timeStr.map(s=>s.padStart(2,'0')).join(':');
}

console.log(formatTime(5000));

\$\endgroup\$
0
\$\begingroup\$

Instead of doing all the math yourself, here's an alternate way to do unit conversions.

I also included a function for zero-padding the numbers to cut down on code repetition.

function zeroPad(number) {
    return String(number).padStart(2, '0')
}

function formatTime(totalSeconds) {
  const second = 1
  const minute = 60*second
  const hour = 60*minute
  const day = 24*hour

  let remainingTime = totalSeconds
  const days = Math.floor(remainingTime/day)
  remainingTime -= days*day
  const hours = Math.floor(remainingTime/hour)
  remainingTime -= hours*hour
  const minutes = Math.floor(remainingTime/minute)
  remainingTime -= minutes*minute
  const seconds = remainingTime/second
  const secondsZPad = seconds < 10 ? `0${seconds}` : seconds;

  let formattedString = `${zeroPad(days)}:${zeroPad(hours)}:${zeroPad(minutes)}:${secondsZPad}`;
  return formattedString;
}

console.log(formatTime(4988.75));

Semantically, multiplying a number by the defined unit (hour = 60*minute) applies the unit to the value and dividing (for example, secondsInDay = 1*day/second) returns the value in another unit. Under the hood, the numeric value is in units of whichever unit was assigned the value 1--second in this case. This is best since the input to the function is already in seconds.

Granted, the last line let seconds = rest/second is somewhat redundant since second = 1, but it keeps with the pattern. However, if totalSeconds could be a floating point number, the zeroPad() function doesn't work since the length of the string is already longer than 2.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.