user2247744
user2247744

Reputation: 135

Calculate duration between two date times in javascript

I need to calculate the duration between two datetimes in JavaScript. I have tried this code:

var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!

var yyyy = today.getFullYear();
if(dd<10){dd='0'+dd} if(mm<10){mm='0'+mm} today = mm+'/'+dd+'/'+yyyy;  //Current Date
console.log("current date"+today);


var valuestart ="8:00 AM";
var valuestop = "4:00 PM";//$("select[name='timestop']").val();

//create date format          
var timeStart = new Date("01/01/2007 " + valuestart).getHours();
var timeEnd = new Date("01/01/2007 " + valuestop).getHours();

var hourDiff = timeEnd - timeStart;             
console.log("duration"+hourDiff);

From this, I am able to get Current Date and duration. But when I replace the date "01/01/2007" with the variable "today", I am getting the result as NaN. Please guide me in where I am wrong. Thanks in advance.

Upvotes: 6

Views: 27242

Answers (6)

DJDaveMark
DJDaveMark

Reputation: 2855

Simple Solution

If your duration is guaranteed to be less than 24 hours and you want to display it to the user here is a very simple solution:

function formatDuration(millis) {
    return new Date(millis).toISOString().substring(11, 19);
}

console.log(formatDuration(59999));    // 00:00:59
console.log(formatDuration(3599999));  // 00:59:59
console.log(formatDuration(86399999)); // 23:59:59

Better Solution

If you want to support years, months & days:

function formatDuration(millis) {
    let date = new Date(millis);
    let parts = [];

    if (date.getUTCFullYear() > 1970) {
        let years = date.getUTCFullYear() - 1970;
        parts.push(years, pluralize(years, 'year'));
    }
    if (date.getUTCMonth() > 0) { // months start at zero
        let months = date.getUTCMonth();
        parts.push(months, pluralize(months, 'month'));
    }
    if (date.getUTCDate() > 1) {
        let days = date.getUTCDate() - 1;
        parts.push(days, pluralize(days, 'day'));
    }

    parts.push(date.toISOString().substring(11, 19));

    return parts.join(' ');
}

function pluralize(count, singular, plural) {
    return count === 1 ? singular : plural ?? `${singular}s`;
}

console.log(formatDuration(new Date('1970-01-01T00:00:59.999Z').getTime())); // 00:00:59
console.log(formatDuration(new Date('1970-01-01T00:59:59.999Z').getTime())); // 00:59:59
console.log(formatDuration(new Date('1970-01-01T23:59:59.999Z').getTime())); // 23:59:59
console.log(formatDuration(new Date('1970-01-31T23:59:59.999Z').getTime())); // 30 days 23:59:59
console.log(formatDuration(new Date('1970-12-01T23:59:59.999Z').getTime())); // 11 months 23:59:59
console.log(formatDuration(new Date('1970-12-31T23:59:59.999Z').getTime())); // 11 months 30 days 23:59:59
console.log(formatDuration(new Date('1971-01-01T23:59:59.999Z').getTime())); // 1 year 23:59:59
console.log(formatDuration(new Date('1971-01-31T23:59:59.999Z').getTime())); // 1 year 30 days 23:59:59
console.log(formatDuration(new Date('1971-12-01T23:59:59.999Z').getTime())); // 1 year 11 months 23:59:59
console.log(formatDuration(new Date('1971-12-31T23:59:59.999Z').getTime())); // 1 year 11 months 30 days 23:59:59

If you want to include the milliseconds use this substring instead:

.substring(11, 23) // 23:59:59.999

and for completeness the JSDoc:

/**
 * Formats a number of milliseconds to `HH:mm:ss`.
 * For durations of 24h and longer, prefixes the number of years, months, days if any are at least 1.
 * Examples:
 * * `00:00:59`
 * * `00:59:59`
 * * `23:59:59`
 * * `30 days 23:59:59`
 * * `11 months 23:59:59`
 * * `11 months 30 days 23:59:59`
 * * `1 year 23:59:59`
 * * `1 year 30 days 23:59:59`
 * * `1 year 11 months 23:59:59`
 * * `1 year 11 months 30 days 23:59:59`
 * @param {number} millis milliseconds
 * @return {string} the time portion in ISO format (excluding milliseconds) i.e. 23:59:59
 */

Upvotes: 0

shawnzhu
shawnzhu

Reputation: 7585

I tried luxon and it's very handy:

Given dt1 and dt2 as ISO representation of date time,

luxon.DateTime.fromISO(dt1).diff(
  luxon.DateTime.fromISO(dt2),
  ['years', 'months', 'days', 'hours', 'minutes', 'seconds']
).values

Upvotes: 0

VincentTu
VincentTu

Reputation: 1

Maybe It's a little bit late. I second the answer from Christophe Roussy. First, calculate the difference in UTC format, then turn the unit - hour. I think it's easier to understand and maintain. Here's the code

var date1 = new Date(`some_valid_start_date_format`);
var date2 = new Date(`some_end_start_date_format`);

var duration = date2.valueOf() - date1.valueOf(); // The unit is millisecond
var hourDiff = parseInt(duration / (60 * 60 * 1000)) // Turn the duration into hour format

Upvotes: 0

Try this :

        var today = new Date();
        var dd = today.getDate();
        var mm = today.getMonth()+1; //January is 0!

        var yyyy = today.getFullYear();
        if(dd<10){dd='0'+dd} if(mm<10){mm='0'+mm} today = dd+'/'+mm+'/'+yyyy;  //Current Date

        var valuestart ="8:00 AM";
        var valuestop = "4:00 PM";//$("select[name='timestop']").val();

        //create date format  
        var timeStart = new Date(today + " " + valuestart).getHours();
        var timeEnd = new Date(today + " " + valuestop).getHours();

        var hourDiff = timeEnd - timeStart;  
        alert("duration:"+hourDiff);

Upvotes: 2

Christophe Roussy
Christophe Roussy

Reputation: 17049

You should work on the epoch milliseconds. The idea is to transform everything to the epoch millis representation, perform your calculations, then go back to another format if needed.

There are many articles on the subject:

Upvotes: 3

KJ Price
KJ Price

Reputation: 5984

today is of Date type whereas "01/01/2007" is a string. Trying to concatenate a Date object with "8:00 AM" will not work. You will have to turn today variable into a string or use today.setHours(8)

Upvotes: 1

Related Questions