1 var totalDaysInMonth = require('./totalDaysInMonth');
2 var totalDaysInYear = require('./totalDaysInYear');
3 var convert = require('../time/convert');
6 * calculate the difference between dates (range)
8 function diff(start, end, unitName){
9 // sort the dates to make it easier to process (specially year/month)
18 if (unitName === 'month') {
19 output = getMonthsDiff(start, end);
20 } else if (unitName === 'year'){
21 output = getYearsDiff(start, end);
22 } else if (unitName != null) {
23 if (unitName === 'day') {
24 // ignore timezone difference because of daylight savings time
28 output = convert(end - start, 'ms', unitName);
38 // we ignore timezone differences on purpose because of daylight
39 // savings time, otherwise it would return fractional days/weeks even
40 // if a full day elapsed. eg:
41 // Wed Feb 12 2014 00:00:00 GMT-0200 (BRST)
42 // Sun Feb 16 2014 00:00:00 GMT-0300 (BRT)
43 // diff should be 4 days and not 4.041666666666667
44 return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(),
45 d.getHours(), d.getMinutes(), d.getSeconds(),
50 function getMonthsDiff(start, end){
51 return getElapsedMonths(start, end) +
52 getElapsedYears(start, end) * 12 +
53 getFractionalMonth(start, end);
57 function getYearsDiff(start, end){
58 var elapsedYears = getElapsedYears(start, end);
59 return elapsedYears + getFractionalYear(start, end, elapsedYears);
63 function getElapsedMonths(start, end){
64 var monthDiff = end.getMonth() - start.getMonth();
68 // less than a full month
69 if (start.getDate() > end.getDate()) {
76 function getElapsedYears(start, end){
77 var yearDiff = end.getFullYear() - start.getFullYear();
78 // less than a full year
79 if (start.getMonth() > end.getMonth()) {
86 function getFractionalMonth(start, end){
87 var fractionalDiff = 0;
88 var startDay = start.getDate();
89 var endDay = end.getDate();
91 if (startDay !== endDay) {
92 var startTotalDays = totalDaysInMonth(start);
93 var endTotalDays = totalDaysInMonth(end);
97 if (startDay > endDay) {
98 // eg: Jan 29 - Feb 27 (29 days elapsed but not a full month)
99 var baseDay = startTotalDays - startDay;
100 daysElapsed = endDay + baseDay;
101 // total days should be relative to 1st day of next month if
102 // startDay > endTotalDays
103 totalDays = (startDay > endTotalDays)?
104 endTotalDays + baseDay + 1 : startDay + baseDay;
106 // fractional is only based on endMonth eg: Jan 12 - Feb 18
107 // (6 fractional days, 28 days until next full month)
108 daysElapsed = endDay - startDay;
109 totalDays = endTotalDays;
112 fractionalDiff = daysElapsed / totalDays;
115 return fractionalDiff;
119 function getFractionalYear(start, end, elapsedYears){
120 var base = elapsedYears?
121 new Date(end.getFullYear(), start.getMonth(), start.getDate()) :
123 var elapsedDays = diff(base, end, 'day');
124 return elapsedDays / totalDaysInYear(end);
128 module.exports = diff;