33

I'm calculating the difference between 2 dates for which there are many differing examples available. The time returned is in milliseconds so I need to convert it into something more useful.

Most examples are for days:hours:minutes:seconds or hours:minutes, but I need days:hours:minutes so the seconds should be rounded up into the minutes.

The method I'm currently using gets close but shows 3 days as 2.23.60 when it should show 3.00.00 so something is not quite right. As I just grabbed the current code from an example on the web, I'm open to suggestions for other ways of doing this.

I'm obtaining the time in milliseconds by subtracting a start date from an end date as follows:-

date1 = new Date(startDateTime);
date2 = new Date(endDateTime);
ms = Math.abs(date1 - date2)

I basically need to take the ms variable and turn in into days.hours:minutes.

Mitch
  • 2,471
  • 8
  • 38
  • 46

14 Answers14

38

Something like this?

function dhm(t){
    var cd = 24 * 60 * 60 * 1000,
        ch = 60 * 60 * 1000,
        d = Math.floor(t / cd),
        h = Math.floor( (t - d * cd) / ch),
        m = Math.round( (t - d * cd - h * ch) / 60000),
        pad = function(n){ return n < 10 ? '0' + n : n; };
  if( m === 60 ){
    h++;
    m = 0;
  }
  if( h === 24 ){
    d++;
    h = 0;
  }
  return [d, pad(h), pad(m)].join(':');
}

console.log( dhm( 3 * 24 * 60 * 60 * 1000 ) );
Mic
  • 24,812
  • 9
  • 57
  • 70
35

Dont know why but the others didn't worked for me so here is mine

function dhm (ms) {
  const days = Math.floor(ms / (24*60*60*1000));
  const daysms = ms % (24*60*60*1000);
  const hours = Math.floor(daysms / (60*60*1000));
  const hoursms = ms % (60*60*1000);
  const minutes = Math.floor(hoursms / (60*1000));
  const minutesms = ms % (60*1000);
  const sec = Math.floor(minutesms / 1000);
  return days + ":" + hours + ":" + minutes + ":" + sec;
}
undefined
  • 1,019
  • 12
  • 24
15

Sounds like a job for Moment.js.

var diff = new moment.duration(ms);
diff.asDays();     // # of days in the duration
diff.asHours();    // # of hours in the duration
diff.asMinutes();  // # of minutes in the duration

There are a ton of other ways to format durations in MomentJS. The docs are very comprehensive.

R3tep
  • 12,512
  • 10
  • 48
  • 75
Brian Kelly
  • 19,067
  • 4
  • 53
  • 55
  • 1
    How would this solve the problem. Wont get the result in desired format. It give total hours, or total minutes or total days. When desired result is total days : hours : minutes – Nitin Kabra Jun 13 '19 at 11:38
  • MomentJS does not have a solution for this. The comment stated above explains it. – Djov Dec 19 '19 at 07:49
  • with respect: question asked explicitely for days:hours:minutes, not for total values. – jasie Dec 17 '20 at 09:41
  • it don't take too much to interpolate the values in a string? the answer, is immensely valuable if you're willing to reach for a dependency. – BenKoshy Apr 20 '22 at 08:57
3

Here you go:

http://jsfiddle.net/uNnfH/1

Or if you don't want to play with a running example, then:

window.minutesPerDay = 60 * 24;

function pad(number) {
    var result = "" + number;
    if (result.length < 2) {
        result = "0" + result;
    }

    return result;
}

function millisToDaysHoursMinutes(millis) {
    var seconds = millis / 1000;
    var totalMinutes = seconds / 60;

    var days = totalMinutes / minutesPerDay;
    totalMinutes -= minutesPerDay * days;
    var hours = totalMinutes / 60;
    totalMinutes -= hours * 60; 

    return days + "." + pad(hours) + "." + pad(totalMinutes);
}
aroth
  • 54,026
  • 20
  • 135
  • 176
  • Thanks for your suggestion aroth, I ended up with many differing approaches and it was a close run thing which one I went with. I hadn't seen jsfiddle before so thanks for introducing me to it. – Mitch Dec 17 '11 at 14:30
2

Dunno how many answers you need, but here's another - just another take on a few answers that have already been given:

function msToDHM(v) {
  var days = v / 8.64e7 | 0;
  var hrs  = (v % 8.64e7)/ 3.6e6 | 0;
  var mins = Math.round((v % 3.6e6) / 6e4);

  return days + ':' + z(hrs) + ':' + z(mins);

  function z(n){return (n<10?'0':'')+n;}
}

Take care with such calculations though, periods crossing daylight saving boundaries will cause issues. Always better to work in UTC and convert to local times for presentation.

RobG
  • 142,382
  • 31
  • 172
  • 209
1

With moment.js try this:

function getFormattedMs(ms) {
  var duration = moment.duration(ms);
  return moment.utc(duration.asMilliseconds()).format("mm:ss");
}

When you want to show hours you have to have a workaround:

function formatDuration(ms) {
  var duration = moment.duration(ms);
  return Math.floor(duration.asHours()) + moment.utc(duration.asMilliseconds()).format(":mm:ss");
}

This workaround in moment was introduced in this Issue.

Robin Wieruch
  • 14,900
  • 10
  • 82
  • 107
1

Adapted from gist.github.com/remino/1563878. Seems a bit clearer to me what's going on.

function convertMS(ms) {
  var d, h, m, s;
  s = Math.floor(ms / 1000);
  m = Math.floor(s / 60);
  s = s % 60;
  h = Math.floor(m / 60);
  m = m % 60;
  d = Math.floor(h / 24);
  h = h % 24;

  var pad = function (n) { return n < 10 ? '0' + n : n; };

  var result = d + '.' + pad(h) + ':' + pad(m);
  return result;
};
MikeT
  • 2,530
  • 25
  • 36
1

"The time returned is in milliseconds so I need to convert it into something more useful."

Are you getting the time back from a server or is this pure javascript?

Some code would really help. "Something useful" is kind of vague.

Here is an example, I think this is what you are talking about.

<script type="text/javascript">

//Set the two dates
var millennium =new Date(2000, 0, 1) //Month is 0-11 in JavaScript
today=new Date()
//Get 1 day in milliseconds
var one_day=1000*60*60*24

//Calculate difference btw the two dates, and convert to days
document.write(Math.ceil((today.getTime()-millennium.getTime())/(one_day))+
" days has gone by since the millennium!")

</script>
4367 days has gone by since the millennium!
Travis J
  • 81,153
  • 41
  • 202
  • 273
  • [There was no year 0](http://en.wikipedia.org/wiki/Year_0). You should use 1/1/2001 as your reference date. – aroth Dec 16 '11 at 00:38
0

Here is my solution in React with moment.js

https://codesandbox.io/s/milliseconds-to-human-readable-text-with-momentjs-in-react-0pgmq

import React from "react";
import ReactDOM from "react-dom";
import moment from "moment";

import "../styles.css";

function App() {
  const oneSecondInMillis = 1000;
  const oneMinuteInMillis = 60000;
  const oneHourInMillis = 3.6e6;
  const oneDayInMillis = 8.64e7;
  const oneMonthMillis = 2.628e9;
  const oneYearInMillis = 3.154e10; //3.154e10;

  const createTime = millis => new moment.duration(millis);

  const millisToReadable = millis => {
    let result = "";

    if (typeof millis !== "number") return "0 ms";

    let time = createTime(millis);

    let years = Math.floor(time.asYears());
    millis = millis - years * oneYearInMillis;
    time = createTime(millis);

    let months = Math.floor(time.asMonths());
    millis = millis - months * oneMonthMillis;
    time = createTime(millis);

    let days = Math.floor(time.asDays());
    millis = millis - days * oneDayInMillis;
    time = createTime(millis);

    let hours = Math.floor(time.asHours());
    millis = millis - hours * oneHourInMillis;
    time = createTime(millis);

    let minutes = Math.floor(time.asMinutes());
    millis = millis - minutes * oneMinuteInMillis;
    time = createTime(millis);

    let seconds = Math.floor(time.asSeconds());
    millis = millis - seconds * oneSecondInMillis;
    time = new moment.duration(millis);

    let milliseconds = Math.floor(time.asMilliseconds());

    if (years > 0) {
      result += ` ${years} y`;
    }
    if (years > 0 || months > 0) {
      result += ` ${months} m`;
    }
    if (years > 0 || months > 0 || days > 0) {
      result += ` ${days} d`;
    }
    if (years > 0 || months > 0 || days > 0 || hours > 0) {
      result += ` ${hours} h`;
    }
    if (years > 0 || months > 0 || days > 0 || hours > 0 || minutes > 0) {
      result += ` ${minutes} m`;
    }
    if (
      years > 0 ||
      months > 0 ||
      days > 0 ||
      hours > 0 ||
      minutes > 0 ||
      seconds > 0
    ) {
      result += ` ${seconds} s`;
    }
    result += ` ${milliseconds} ms`;

    return result;
  };

  const millis =
    2 * oneYearInMillis +
    7 * oneMonthMillis +
    20 * oneDayInMillis +
    10 * oneHourInMillis +
    8 * oneMinuteInMillis +
    50 * oneSecondInMillis +
    95;

  const result = millisToReadable(millis);

  return (
    <div className="App">
      <h1>Milliseconds to Human Readable Text</h1>
      <h2>{millis}</h2>
      <h2>{result}</h2>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
serdarsen
  • 193
  • 2
  • 8
0

To extend "moment.js" with extra function formatDuration to properly format intervals add this script:

this.moment.formatDuration = function (duration, timeFormat) {
    const ms = duration.asMilliseconds(),
        days = Math.floor(Math.abs(ms) / 8.64e7),
        msOnLastDay = Math.abs(ms) - days * 8.64e7;
    return (ms < 0 ? '-' : '') + (days !== 0 ? days + ' ' : '')
        + moment.utc(msOnLastDay).format(timeFormat ? timeFormat : 'HH:mm:ss.SSS');
};

Like 10 seconds will be displayed as "00:00:10.000". Difference in two days, one hour and 25 minutes will be displayed as "2 01:25:00.000". Time format can be customized.

See running example in JSFiddle - https://jsfiddle.net/aldis/9x3f8b7q

Aldis
  • 439
  • 4
  • 10
0

This library seems to be fairly useful for parsing milliseconds. It gives you an object with properties like days, hours, minutes, etc...

https://www.npmjs.com/package/parse-ms

And this one does pretty printing of milliseconds:

https://github.com/sindresorhus/pretty-ms

Kimball Robinson
  • 3,287
  • 9
  • 47
  • 59
0

I've made a version that shows the days only if needed as well as the padding for hours.

const padZeroTwo = (n) => ('' + n).padStart(2, '0');
const msToDaysHoursMinutes = (ms) => {
  const days = Math.floor(ms / (24 * 60 * 60 * 1000));
  const daysMs = ms % (24 * 60 * 60 * 1000);
  const hours = Math.floor(daysMs / (60 * 60 * 1000));
  const hoursMs = ms % (60 * 60 * 1000);
  const minutes = Math.round(hoursMs / (60 * 1000)); // Rounds up to minutes

  let output = '';

  if (days > 0) {
    output += days + ':';
  }

  output += (days > 0 ? padZeroTwo(hours) : hours) + ':';
  output += padZeroTwo(minutes);

  return output;
};

// Tests
const hundredDaysTwentyHoursFiftyMinutesThirtySeconds = 8715030000;
const oneDayTwoHoursEightMinutesTwelveSeconds = 94092000;
const twoHoursFiftyMinutes = 10200000;
const twelveSeconds = 12000;
const fiftySeconds = 50000;

console.log(msToDaysHoursMinutes(hundredDaysTwentyHoursFiftyMinutesThirtySeconds)); // 100:20:51
console.log(msToDaysHoursMinutes(oneDayTwoHoursEightMinutesTwelveSeconds)); // 1:02:08
console.log(msToDaysHoursMinutes(twoHoursFiftyMinutes)); // 2:50
console.log(msToDaysHoursMinutes(twelveSeconds)); // 0:00
console.log(msToDaysHoursMinutes(fiftySeconds)); // 0:01
Jonathan
  • 8,771
  • 4
  • 41
  • 78
0
   const convertMsToDHM = (miliseconds) => {
  let days;
  let hours;
  let minutes;
  let seconds;
  let total_hours;
  let total_minutes;
  let total_seconds;

  total_seconds = parseInt(Math.floor(miliseconds / 1000));
  total_minutes = parseInt(Math.floor(total_seconds / 60));
  total_hours = parseInt(Math.floor(total_minutes / 60));
  days = parseInt(Math.floor(total_hours / 24));

  seconds = parseInt(total_seconds % 60);
  minutes = parseInt(total_minutes % 60);
  hours = parseInt(total_hours % 24);
  return `${padTo2Digits(days)}:${padTo2Digits(hours)}:${padTo2Digits(minutes)}`;
};

const padTo2Digits = num => num.toString().padStart(2, '0');
Pramod Ukkali
  • 261
  • 2
  • 2
0

Without code, it's hard to tell exactly which error you have, but I suspect you're doing exactly as you said: rounding up. If rounding down is not good enough for you, here's how to round to closest:

var time = date.getTime();
if (time % 60000 >= 30000) time += 60000;

and then continue with the calculation.

Amadan
  • 191,408
  • 23
  • 240
  • 301