Languages
[Edit]
EN

JavaScript - how to calculate time period (time difference in days, minutes, seconds and milliseconds)?

2 points
Created by:
JustMike
3515

In this article, we're going to have a look at how to calculate time between two dates in JavaScript.

First thing that we should mention is fact the number of days in different months and years is different so the easiest way is to express it is number of days, hours, minutes, seconds and milliseconds.

1. Custom time period example

In this section dates are converted to milliseconds difference. Basing on the difference we are able in simple way to calculate amount of days, hours, minutes, etc.

// ONLINE-RUNNER:browser;

var units = [
  	{name: 'milliseconds', scale: 1000},
  	{name: 'seconds', scale: 60},
  	{name: 'minutes', scale: 60},
  	{name: 'hours', scale: 24}
];

// calculates difference between dates
function calculatePeriod(t1, t2) {
    var dt = t2 - t1;
	var result = { };
	for(var i = 0; i < units.length; ++i) {
		var unit = units[i];
		var total = Math.floor(dt / unit.scale);
		var rest = dt - total * unit.scale;
		result[unit.name] = rest;
		dt = total;
	}
	result.days = dt;
  	return result;
}

// calculates difference between dates and creates string
function renderPeriod(t1, t2) {
    var period = calculatePeriod(t1, t2);
    var result = '';
  	function addPart(value, unit) {
      	if (value) {
            if (result) {
                result += ' ';
            }
            result += value + ' ' + (value === 1 ? unit : unit + 's');
        }
    }
  	addPart(period.days, 'day');
    addPart(period.hours, 'hour');
    addPart(period.minutes, 'minute');
    addPart(period.seconds, 'second');
  	addPart(period.milliseconds, 'millisecond');
  	return result || 'dates are same';
}

// Usage example:

var t0 = new Date(2000, 0, 1);                    // 1 January 2000, 00:00:00.000

var t1 = new Date(2000,  0, 1);                   // 1 January 2000, 00:00:00.000
var t2 = new Date(2000,  0, 1,  0,  0,  0, 999);  // 1 January 2000, 00:00:00.999
var t3 = new Date(2000,  0, 1,  0,  0, 30, 999);  // 1 January 2000, 00:00:30.999
var t4 = new Date(2000,  0, 1,  0, 10, 30, 999);  // 1 January 2000, 00:10:30.999
var t5 = new Date(2000,  0, 1, 15, 10, 30, 999);  // 1 January 2000, 15:10:30.999
var t6 = new Date(2000,  0, 5, 15, 10, 30, 999);  // 5 January 2000, 15:10:30.999
var t7 = new Date(2000, 10, 5, 15, 10, 30, 999);  // 5 November 2000, 15:10:30.999
var t8 = new Date(2015, 10, 5, 15, 10, 30, 999);  // 5 November 2015, 15:10:30.999
var t9 = new Date();                              // current date and time

console.log(renderPeriod(t0, t1));  // dates are same
console.log(renderPeriod(t0, t2));  // 999 milliseconds
console.log(renderPeriod(t0, t3));  // 30 seconds 999 milliseconds
console.log(renderPeriod(t0, t4));  // 10 minutes 30 seconds 999 milliseconds
console.log(renderPeriod(t0, t5));  // 15 hours 10 minutes 30 seconds 999 milliseconds
console.log(renderPeriod(t0, t6));  // 4 days 15 hours 10 minutes 30 seconds 999 milliseconds
console.log(renderPeriod(t0, t7));  // 309 days 15 hours 10 minutes 30 seconds 999 milliseconds
console.log(renderPeriod(t0, t8));  // 5787 days 15 hours 10 minutes 30 seconds 999 milliseconds
console.log(renderPeriod(t0, t9));  // <current_date_and_time> - t0

2. Alternative implementation example

This approach allows to:

  • render string with indicated amount of parts (e.g. 2 parts 10s 30min) ,
  • use custom units (labels array as last argument),
  • select message to display when precision of labels is not enought (e.g. done variable can be set as 'Now' when we want to say comment was posted now - not 100ms ago).

Note:

  • this approach is not perfect because of different days per one year, but for displaying aproximate period time it is enought (e.g. comments system),
  • to solve the problem we can remove years part from code.
// ONLINE-RUNNER:browser;

var TimeUtils = new function() {
    
    var UNITS = [
        {name: 'milliseconds', scale: 1000},
        {name: 'seconds',      scale: 60},
        {name: 'minutes',      scale: 60},
        {name: 'hours',        scale: 24},
        {name: 'days',         scale: 30},
        {name: 'months',       scale: 12}
    ];
    var LABELS = [
        {name: 'years',   unit: 'y'},
        {name: 'months',  unit: 'm'},
        {name: 'days',    unit: 'd'},
        {name: 'hours',   unit: 'h'},
        {name: 'minutes', unit: 'min'},
        {name: 'seconds', unit: 's'}
    ];

    var self = this;

    function renderPart(period, label) {
        var value = period[label.name];
        if (value) {
            return value + label.unit;
        }
        return null;
    }

    self.calculatePeriod = function(t1, t2, units) {
        if(units == null) {
            units = UNITS;
        }
        var dt = t2 - t1;
        var result = { };
        for(var i = 0; i < units.length; ++i) {
            var unit = units[i];
            var total = Math.floor(dt / unit.scale);
            var rest = dt - total * unit.scale;
            result[unit.name] = rest;
            dt = total;
        }
        result.years = dt;
        return result;
    };

    // Renders period (timespan / moment) string.
    //
    // period - rendered period
    // done - returned string when period is smaller than labels precision
    // size - number or rendered parts (for 2 renders '[value1][unit2] [value2][unit2]')
    // labels - array of own custom labels
    //
    self.renderPeriod$1 = function(period, done, size, labels) {
        if (labels == null) {
            labels = LABELS;
        }
        if (size == null) {
            size = 2;
        }
        var result = '';
        for (var i = 0; i < labels.length && size > 0; ++i) {
            var part = renderPart(period, labels[i]);
            if (part) {
                if (result) {
                    result += ' ';
                }
                size -= 1;
                result += part;
            } else {
                if (result) {
                    break;
                }
            }
        }
        return result || done || '0ms';
    };

    // Renders period (timespan / moment) string for difference between current system time and t2.
    //
    // time - time of event
    // done - returned string when period is smaller than labels precision
    // size - number or rendered parts (for 2 renders '[value1][unit2] [value2][unit2]')
    // labels - array of own custom labels
    //
    self.renderPeriod$2 = function(time, done, size, labels) {
        var now = self.getTime();
        return self.renderPeriod$2(time, now, done, size, labels);
    };

    // Renders period (timespan / moment) string for difference between t1 and t2.
    //
    // t1 - start time
    // t2 - end time
    // done - returned string when period is smaller than labels precision
    // size - number or rendered parts (for 2 renders '[value1][unit2] [value2][unit2]')
    // labels - array of own custom labels
    //
    self.renderPeriod$3 = function(t1, t2, done, size, labels) {
        var period = self.calculatePeriod(t1, t2);
        return self.renderPeriod$1(period, done, size, labels);
    };
};

// Usage example 1:

//                                   t1            t2
console.log(TimeUtils.renderPeriod$3(0,                       1000));  // 1s
console.log(TimeUtils.renderPeriod$3(0,                  30 * 1000));  // 30s
console.log(TimeUtils.renderPeriod$3(0, 10 * 60 * 1000 + 30 * 1000));  // 10min 30s

// Usage example 2:

var t0 = new Date(2000, 0, 1);                    // 1 January 2000, 00:00:00.000

var t1 = new Date(2000,  0, 1);                   // 1 January 2000, 00:00:00.000
var t2 = new Date(2000,  0, 1,  0,  0,  0, 999);  // 1 January 2000, 00:00:00.999
var t3 = new Date(2000,  0, 1,  0,  0, 30, 999);  // 1 January 2000, 00:00:30.999
var t4 = new Date(2000,  0, 1,  0, 10, 30, 999);  // 1 January 2000, 00:10:30.999
var t5 = new Date(2000,  0, 1, 15, 10, 30, 999);  // 1 January 2000, 15:10:30.999
var t6 = new Date(2000,  0, 5, 15, 10, 30, 999);  // 5 January 2000, 15:10:30.999
var t7 = new Date(2000, 10, 5, 15, 10, 30, 999);  // 5 November 2000, 15:10:30.999
var t8 = new Date(2015, 10, 5, 15, 10, 30, 999);  // 5 November 2015, 15:10:30.999
var t9 = new Date();                              // current date and time

console.log(TimeUtils.renderPeriod$3(t0, t1, 'Now'  ));  // Now
console.log(TimeUtils.renderPeriod$3(t0, t2, '0'    ));  // 0
console.log(TimeUtils.renderPeriod$3(t0, t3, null, 5));  // 30s
console.log(TimeUtils.renderPeriod$3(t0, t4, null, 5));  // 10min 30s
console.log(TimeUtils.renderPeriod$3(t0, t5, null, 5));  // 15h 10min 30s
console.log(TimeUtils.renderPeriod$3(t0, t6, null, 5));  // 4d 15h 10min 30s
console.log(TimeUtils.renderPeriod$3(t0, t7, null, 5));  // 10m 9d 15h 10min 30s
console.log(TimeUtils.renderPeriod$3(t0, t8, null, 5));  // 16y
console.log(TimeUtils.renderPeriod$3(t0, t9, null, 5));  // <current_date_and_time> - t0
Hey 👋
Would you like to know what we do?
  • Dirask is a friendly IT community for learners, professionals and hobbyists to share their knowledge and help each other in extraordinary easy way.
  • We welcome everyone,
    no matter what the experience,
    no matter how basic the question is,
    this community will help you.