123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- var totalDaysInMonth = require('./totalDaysInMonth');
- var totalDaysInYear = require('./totalDaysInYear');
- var convert = require('../time/convert');
- /**
- * calculate the difference between dates (range)
- */
- function diff(start, end, unitName){
- // sort the dates to make it easier to process (specially year/month)
- if (start > end) {
- var swap = start;
- start = end;
- end = swap;
- }
- var output;
- if (unitName === 'month') {
- output = getMonthsDiff(start, end);
- } else if (unitName === 'year'){
- output = getYearsDiff(start, end);
- } else if (unitName != null) {
- if (unitName === 'day') {
- // ignore timezone difference because of daylight savings time
- start = toUtc(start);
- end = toUtc(end);
- }
- output = convert(end - start, 'ms', unitName);
- } else {
- output = end - start;
- }
- return output;
- }
- function toUtc(d){
- // we ignore timezone differences on purpose because of daylight
- // savings time, otherwise it would return fractional days/weeks even
- // if a full day elapsed. eg:
- // Wed Feb 12 2014 00:00:00 GMT-0200 (BRST)
- // Sun Feb 16 2014 00:00:00 GMT-0300 (BRT)
- // diff should be 4 days and not 4.041666666666667
- return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(),
- d.getHours(), d.getMinutes(), d.getSeconds(),
- d.getMilliseconds());
- }
- function getMonthsDiff(start, end){
- return getElapsedMonths(start, end) +
- getElapsedYears(start, end) * 12 +
- getFractionalMonth(start, end);
- }
- function getYearsDiff(start, end){
- var elapsedYears = getElapsedYears(start, end);
- return elapsedYears + getFractionalYear(start, end, elapsedYears);
- }
- function getElapsedMonths(start, end){
- var monthDiff = end.getMonth() - start.getMonth();
- if (monthDiff < 0) {
- monthDiff += 12;
- }
- // less than a full month
- if (start.getDate() > end.getDate()) {
- monthDiff -= 1;
- }
- return monthDiff;
- }
- function getElapsedYears(start, end){
- var yearDiff = end.getFullYear() - start.getFullYear();
- // less than a full year
- if (start.getMonth() > end.getMonth()) {
- yearDiff -= 1;
- }
- return yearDiff;
- }
- function getFractionalMonth(start, end){
- var fractionalDiff = 0;
- var startDay = start.getDate();
- var endDay = end.getDate();
- if (startDay !== endDay) {
- var startTotalDays = totalDaysInMonth(start);
- var endTotalDays = totalDaysInMonth(end);
- var totalDays;
- var daysElapsed;
- if (startDay > endDay) {
- // eg: Jan 29 - Feb 27 (29 days elapsed but not a full month)
- var baseDay = startTotalDays - startDay;
- daysElapsed = endDay + baseDay;
- // total days should be relative to 1st day of next month if
- // startDay > endTotalDays
- totalDays = (startDay > endTotalDays)?
- endTotalDays + baseDay + 1 : startDay + baseDay;
- } else {
- // fractional is only based on endMonth eg: Jan 12 - Feb 18
- // (6 fractional days, 28 days until next full month)
- daysElapsed = endDay - startDay;
- totalDays = endTotalDays;
- }
- fractionalDiff = daysElapsed / totalDays;
- }
- return fractionalDiff;
- }
- function getFractionalYear(start, end, elapsedYears){
- var base = elapsedYears?
- new Date(end.getFullYear(), start.getMonth(), start.getDate()) :
- start;
- var elapsedDays = diff(base, end, 'day');
- return elapsedDays / totalDaysInYear(end);
- }
- module.exports = diff;
|