import absFloor from '../utils/abs-floor';
|
import { cloneWithOffset } from '../units/offset';
|
import { normalizeUnits } from '../units/aliases';
|
|
export function diff(input, units, asFloat) {
|
var that, zoneDelta, output;
|
|
if (!this.isValid()) {
|
return NaN;
|
}
|
|
that = cloneWithOffset(input, this);
|
|
if (!that.isValid()) {
|
return NaN;
|
}
|
|
zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
|
|
units = normalizeUnits(units);
|
|
switch (units) {
|
case 'year':
|
output = monthDiff(this, that) / 12;
|
break;
|
case 'month':
|
output = monthDiff(this, that);
|
break;
|
case 'quarter':
|
output = monthDiff(this, that) / 3;
|
break;
|
case 'second':
|
output = (this - that) / 1e3;
|
break; // 1000
|
case 'minute':
|
output = (this - that) / 6e4;
|
break; // 1000 * 60
|
case 'hour':
|
output = (this - that) / 36e5;
|
break; // 1000 * 60 * 60
|
case 'day':
|
output = (this - that - zoneDelta) / 864e5;
|
break; // 1000 * 60 * 60 * 24, negate dst
|
case 'week':
|
output = (this - that - zoneDelta) / 6048e5;
|
break; // 1000 * 60 * 60 * 24 * 7, negate dst
|
default:
|
output = this - that;
|
}
|
|
return asFloat ? output : absFloor(output);
|
}
|
|
function monthDiff(a, b) {
|
if (a.date() < b.date()) {
|
// end-of-month calculations work correct when the start month has more
|
// days than the end month.
|
return -monthDiff(b, a);
|
}
|
// difference in months
|
var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
|
// b is in (anchor - 1 month, anchor + 1 month)
|
anchor = a.clone().add(wholeMonthDiff, 'months'),
|
anchor2,
|
adjust;
|
|
if (b - anchor < 0) {
|
anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
|
// linear across the month
|
adjust = (b - anchor) / (anchor - anchor2);
|
} else {
|
anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
|
// linear across the month
|
adjust = (b - anchor) / (anchor2 - anchor);
|
}
|
|
//check for negative zero, return zero if negative zero
|
return -(wholeMonthDiff + adjust) || 0;
|
}
|