EN
JavaScript - calculate time period (time difference in days, minutes, seconds and milliseconds)
5 points
In this article, we're going to have a look at how to calculate the time period between two dates in JavaScript.
The first thing that we should mention is the fact the number of days in different months and years is different so the easiest way is to express it as a number of days, hours, minutes, seconds, and milliseconds.
In this section, dates are converted to milliseconds difference. Based on the difference we are able in a simple way to calculate the amount of days, hours, minutes, etc.
xxxxxxxxxx
1
var units = [
2
{name: 'milliseconds', scale: 1000},
3
{name: 'seconds', scale: 60},
4
{name: 'minutes', scale: 60},
5
{name: 'hours', scale: 24}
6
];
7
8
// Calculates difference between dates.
9
//
10
function calculatePeriod(t1, t2) {
11
var dt = t2 - t1;
12
var result = { };
13
for(var i = 0; i < units.length; ++i) {
14
var unit = units[i];
15
var total = Math.floor(dt / unit.scale);
16
var rest = dt - total * unit.scale;
17
result[unit.name] = rest;
18
dt = total;
19
}
20
result.days = dt;
21
return result;
22
}
23
24
// Calculates difference between dates and creates string.
25
//
26
function renderPeriod(t1, t2) {
27
var period = calculatePeriod(t1, t2);
28
var result = '';
29
function addPart(value, unit) {
30
if (value) {
31
if (result) {
32
result += ' ';
33
}
34
result += value + ' ' + (value === 1 ? unit : unit + 's');
35
}
36
}
37
addPart(period.days, 'day');
38
addPart(period.hours, 'hour');
39
addPart(period.minutes, 'minute');
40
addPart(period.seconds, 'second');
41
addPart(period.milliseconds, 'millisecond');
42
return result || 'dates are same';
43
}
44
45
46
// Usage example:
47
48
var t0 = new Date(2000, 0, 1); // 1 January 2000, 00:00:00.000
49
50
var t1 = new Date(2000, 0, 1); // 1 January 2000, 00:00:00.000
51
var t2 = new Date(2000, 0, 1, 0, 0, 0, 999); // 1 January 2000, 00:00:00.999
52
var t3 = new Date(2000, 0, 1, 0, 0, 30, 999); // 1 January 2000, 00:00:30.999
53
var t4 = new Date(2000, 0, 1, 0, 10, 30, 999); // 1 January 2000, 00:10:30.999
54
var t5 = new Date(2000, 0, 1, 15, 10, 30, 999); // 1 January 2000, 15:10:30.999
55
var t6 = new Date(2000, 0, 5, 15, 10, 30, 999); // 5 January 2000, 15:10:30.999
56
var t7 = new Date(2000, 10, 5, 15, 10, 30, 999); // 5 November 2000, 15:10:30.999
57
var t8 = new Date(2015, 10, 5, 15, 10, 30, 999); // 5 November 2015, 15:10:30.999
58
var t9 = new Date(); // current date and time
59
60
console.log(renderPeriod(t0, t1)); // dates are same
61
console.log(renderPeriod(t0, t2)); // 999 milliseconds
62
console.log(renderPeriod(t0, t3)); // 30 seconds 999 milliseconds
63
console.log(renderPeriod(t0, t4)); // 10 minutes 30 seconds 999 milliseconds
64
console.log(renderPeriod(t0, t5)); // 15 hours 10 minutes 30 seconds 999 milliseconds
65
console.log(renderPeriod(t0, t6)); // 4 days 15 hours 10 minutes 30 seconds 999 milliseconds
66
console.log(renderPeriod(t0, t7)); // 309 days 15 hours 10 minutes 30 seconds 999 milliseconds
67
console.log(renderPeriod(t0, t8)); // 5787 days 15 hours 10 minutes 30 seconds 999 milliseconds
68
console.log(renderPeriod(t0, t9)); // <current_date_and_time> - t0
This approach allows to:
- render string with the indicated amount of parts (e.g. 2 parts
10s 30min
), - use custom units (
labels
array as the last argument), - select a message to display when the precision of labels is not enough (e.g.
done
variable can be set as'Now'
when we want to say the 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.
xxxxxxxxxx
1
var TimeUtils = new function() {
2
3
var UNITS = [
4
{name: 'milliseconds', scale: 1000},
5
{name: 'seconds', scale: 60},
6
{name: 'minutes', scale: 60},
7
{name: 'hours', scale: 24},
8
{name: 'days', scale: 30},
9
{name: 'months', scale: 12}
10
];
11
var LABELS = [
12
{name: 'years', unit: 'y'},
13
{name: 'months', unit: 'm'},
14
{name: 'days', unit: 'd'},
15
{name: 'hours', unit: 'h'},
16
{name: 'minutes', unit: 'min'},
17
{name: 'seconds', unit: 's'}
18
];
19
20
var self = this;
21
22
function renderPart(period, label) {
23
var value = period[label.name];
24
if (value) {
25
return value + label.unit;
26
}
27
return null;
28
}
29
30
self.calculatePeriod = function(t1, t2, units) {
31
if(units == null) {
32
units = UNITS;
33
}
34
var dt = t2 - t1;
35
var result = { };
36
for(var i = 0; i < units.length; ++i) {
37
var unit = units[i];
38
var total = Math.floor(dt / unit.scale);
39
var rest = dt - total * unit.scale;
40
result[unit.name] = rest;
41
dt = total;
42
}
43
result.years = dt;
44
return result;
45
};
46
47
// Renders period (timespan / moment) string.
48
//
49
// period - rendered period
50
// done - returned string when period is smaller than labels precision
51
// size - number or rendered parts (for 2 renders '[value1][unit2] [value2][unit2]')
52
// labels - array of own custom labels
53
//
54
self.renderPeriod$1 = function(period, done, size, labels) {
55
if (labels == null) {
56
labels = LABELS;
57
}
58
if (size == null) {
59
size = 2;
60
}
61
var result = '';
62
for (var i = 0; i < labels.length && size > 0; ++i) {
63
var part = renderPart(period, labels[i]);
64
if (part) {
65
if (result) {
66
result += ' ';
67
}
68
size -= 1;
69
result += part;
70
} else {
71
if (result) {
72
break;
73
}
74
}
75
}
76
return result || done || '0ms';
77
};
78
79
// Renders period (timespan / moment) string for difference between current system time and t2.
80
//
81
// time - time of event
82
// done - returned string when period is smaller than labels precision
83
// size - number or rendered parts (for 2 renders '[value1][unit2] [value2][unit2]')
84
// labels - array of own custom labels
85
//
86
self.renderPeriod$2 = function(time, done, size, labels) {
87
var now = self.getTime();
88
return self.renderPeriod$2(time, now, done, size, labels);
89
};
90
91
// Renders period (timespan / moment) string for difference between t1 and t2.
92
//
93
// t1 - start time
94
// t2 - end time
95
// done - returned string when period is smaller than labels precision
96
// size - number or rendered parts (for 2 renders '[value1][unit2] [value2][unit2]')
97
// labels - array of own custom labels
98
//
99
self.renderPeriod$3 = function(t1, t2, done, size, labels) {
100
var period = self.calculatePeriod(t1, t2);
101
return self.renderPeriod$1(period, done, size, labels);
102
};
103
};
104
105
106
// Usage example 1:
107
108
// t1 t2
109
console.log(TimeUtils.renderPeriod$3(0, 1000)); // 1s
110
console.log(TimeUtils.renderPeriod$3(0, 30 * 1000)); // 30s
111
console.log(TimeUtils.renderPeriod$3(0, 10 * 60 * 1000 + 30 * 1000)); // 10min 30s
112
113
114
// Usage example 2:
115
116
var t0 = new Date(2000, 0, 1); // 1 January 2000, 00:00:00.000
117
118
var t1 = new Date(2000, 0, 1); // 1 January 2000, 00:00:00.000
119
var t2 = new Date(2000, 0, 1, 0, 0, 0, 999); // 1 January 2000, 00:00:00.999
120
var t3 = new Date(2000, 0, 1, 0, 0, 30, 999); // 1 January 2000, 00:00:30.999
121
var t4 = new Date(2000, 0, 1, 0, 10, 30, 999); // 1 January 2000, 00:10:30.999
122
var t5 = new Date(2000, 0, 1, 15, 10, 30, 999); // 1 January 2000, 15:10:30.999
123
var t6 = new Date(2000, 0, 5, 15, 10, 30, 999); // 5 January 2000, 15:10:30.999
124
var t7 = new Date(2000, 10, 5, 15, 10, 30, 999); // 5 November 2000, 15:10:30.999
125
var t8 = new Date(2015, 10, 5, 15, 10, 30, 999); // 5 November 2015, 15:10:30.999
126
var t9 = new Date(); // current date and time
127
128
console.log(TimeUtils.renderPeriod$3(t0, t1, 'Now' )); // Now
129
console.log(TimeUtils.renderPeriod$3(t0, t2, '0' )); // 0
130
console.log(TimeUtils.renderPeriod$3(t0, t3, null, 5)); // 30s
131
console.log(TimeUtils.renderPeriod$3(t0, t4, null, 5)); // 10min 30s
132
console.log(TimeUtils.renderPeriod$3(t0, t5, null, 5)); // 15h 10min 30s
133
console.log(TimeUtils.renderPeriod$3(t0, t6, null, 5)); // 4d 15h 10min 30s
134
console.log(TimeUtils.renderPeriod$3(t0, t7, null, 5)); // 10m 9d 15h 10min 30s
135
console.log(TimeUtils.renderPeriod$3(t0, t8, null, 5)); // 16y
136
console.log(TimeUtils.renderPeriod$3(t0, t9, null, 5)); // <current_date_and_time> - t0