Skip to content

Instantly share code, notes, and snippets.

@nicholaskajoh
Last active July 19, 2018 13:51
Show Gist options
  • Save nicholaskajoh/5528a626dd9bf1472bf3a61a97034a89 to your computer and use it in GitHub Desktop.
Save nicholaskajoh/5528a626dd9bf1472bf3a61a97034a89 to your computer and use it in GitHub Desktop.
/* calculate the difference in minutes between 2 date times
given that only the minutes within a specified time range
every day should be counted
e.g: say the time range is 6AM to 6PM
if datetime1 = 4AM and datetime2 = 5AM, difference = 0 minutes
this is because 4AM to 5AM doesn't fall within the range of
6AM to 6PM so the 60 minutes isn't counted
e.g 2: say we have same time range and,
datetime1 = 5AM today and datetime2 = 7PM tomorrow,
difference = 1440 minutes
this is because, between 5AM today and 7PM tomorrow, there are
24 x 60 minutes within the range of 6AM and 6PM
In this function, we call this range "working hours", or WH
So we have a WH_START and WH_END
NB: We assume all datetimes are in UTC i.e 2011-04-11T10:20:30Z
Also, datetime1 < datetime2
*/
function datetimeDiff(datetime1, datetime2) {
const WH_START = '06:00:00';
const WH_END = '18:00:00';
const maxDatetime = (x, y) => x > y ? x: y;
const minDatetime = (x, y) => x < y ? x: y;
let totalMinutesDifference = 0;
let todaysDate = new Date(`${datetime1.toISOString().split('T')[0]}T00:00:00Z`);
const endDate = new Date(`${datetime2.toISOString().split('T')[0]}T00:00:00Z`);
let WHTodayStart = new Date(`${datetime1.toISOString().split('T')[0]}T${WH_START}Z`);
let WHTodayEnd = new Date(`${datetime1.toISOString().split('T')[0]}T${WH_END}Z`);
let todayStarts = datetime1;
let todayEnds = datetime2 < WHTodayEnd ? datetime2: WHTodayEnd;
while (todaysDate <= endDate) {
let p = maxDatetime(todayStarts, WHTodayStart);
let q = minDatetime(todayEnds, WHTodayEnd);
let minutesDifference = (q - p) / (60 * 1000);
minutesDifference = minutesDifference > 0 ? minutesDifference: 0;
totalMinutesDifference += minutesDifference;
WHTodayStart.setHours(WHTodayStart.getHours() + 24);
WHTodayEnd.setHours(WHTodayEnd.getHours() + 24);
todaysDate.setHours(todaysDate.getHours() + 24);
todayStarts = WHTodayStart;
todayEnds = datetime2 < WHTodayEnd ? datetime2: WHTodayEnd;
}
return totalMinutesDifference;
}
// TEST
testCases = [
{ dt1: new Date('2012-12-12T04:00:00Z'), dt2: new Date('2012-12-12T05:00:00Z'), diff: 0 },
{ dt1: new Date('2012-12-12T18:00:00Z'), dt2: new Date('2012-12-12T20:00:00Z'), diff: 0 },
{ dt1: new Date('2012-12-12T04:00:00Z'), dt2: new Date('2012-12-12T07:00:00Z'), diff: 60 },
{ dt1: new Date('2012-12-12T12:00:00Z'), dt2: new Date('2012-12-12T14:00:00Z'), diff: 120 },
{ dt1: new Date('2012-12-12T15:00:00Z'), dt2: new Date('2012-12-12T19:00:00Z'), diff: 180 },
{ dt1: new Date('2012-12-12T05:00:00Z'), dt2: new Date('2012-12-13T19:00:00Z'), diff: 1440 },
{ dt1: new Date('2012-12-12T10:00:00Z'), dt2: new Date('2012-12-13T19:00:00Z'), diff: 1200 },
{ dt1: new Date('2012-12-12T08:00:00Z'), dt2: new Date('2012-12-15T15:00:00Z'), diff: 2580 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), diff: 0 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 10, 17, 39, 33)), diff: 600 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 7, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 7, 40, 33)), diff: 721 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 5, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 10, 8, 39, 33)), diff: 159.55 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 8, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 8, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 8, 39, 33)), diff: 780 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 7, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 6, 39, 33)), diff: 660 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 9, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 8, 39, 33)), diff: 660 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 16, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 10, 23, 39, 33)), diff: 80.45 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 16, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 23, 39, 33)), diff: 800.45 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 16, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 7, 39, 33)), diff: 180 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 16, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 8, 39, 33)), diff: 240 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 20, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 8, 39, 33)), diff: 159.55 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 19, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 10, 21, 39, 33)), diff: 0 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 19, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 2, 39, 33)), diff: 0 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 3, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 20, 2, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 3, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 20, 4, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 2, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 20, 3, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 4, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 20, 3, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 20, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 21, 20, 39, 33)), diff: 1440 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 21, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 21, 20, 39, 33)), diff: 1440 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 19, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 21, 20, 39, 33)), diff: 1440 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 20, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 21, 21, 39, 33)), diff: 1440 },
{ dt1: new Date(Date.UTC(2018, 10, 19, 20, 39, 33)), dt2: new Date(Date.UTC(2018, 10, 21, 19, 39, 33)), diff: 1440 },
{ dt1: new Date(Date.UTC(2018, 9, 19, 18, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 20, 17, 39, 33)), diff: 699.55 },
{ dt1: new Date(Date.UTC(2018, 9, 19, 20, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 20, 1, 39, 33)), diff: 0 },
{ dt1: new Date(Date.UTC(2018, 9, 20, 6, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 22, 0, 39, 33)), diff: 1400.45 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 6, 0, 0)), dt2: new Date(Date.UTC(2018, 9, 10, 8, 0, 0)), diff: 120 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 6, 0, 0)), dt2: new Date(Date.UTC(2018, 9, 10, 6, 0, 0)), diff: 0 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 6, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 12, 6, 39, 33)), diff: 1440 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 6, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 6, 39, 33)), diff: 720 },
{ dt1: new Date(Date.UTC(2018, 9, 10, 6, 39, 33)), dt2: new Date(Date.UTC(2018, 9, 11, 7, 39, 33)), diff: 780 },
];
for(let testCase of testCases) {
let diff = datetimeDiff(testCase.dt1, testCase.dt2);
let status = diff === testCase.diff ? 'PASS': 'FAIL';
console.log(`Expected: ${testCase.diff} minutes, Output: ${diff} minutes, Status: ${status}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment