1import absFloor from '../utils/abs-floor';
2import { cloneWithOffset } from '../units/offset';
3import { normalizeUnits } from '../units/aliases';
4
5export function diff(input, units, asFloat) {
6 var that, zoneDelta, output;
7
8 if (!this.isValid()) {
9 return NaN;
10 }
11
12 that = cloneWithOffset(input, this);
13
14 if (!that.isValid()) {
15 return NaN;
16 }
17
18 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
19
20 units = normalizeUnits(units);
21
22 switch (units) {
23 case 'year':
24 output = monthDiff(this, that) / 12;
25 break;
26 case 'month':
27 output = monthDiff(this, that);
28 break;
29 case 'quarter':
30 output = monthDiff(this, that) / 3;
31 break;
32 case 'second':
33 output = (this - that) / 1e3;
34 break; // 1000
35 case 'minute':
36 output = (this - that) / 6e4;
37 break; // 1000 * 60
38 case 'hour':
39 output = (this - that) / 36e5;
40 break; // 1000 * 60 * 60
41 case 'day':
42 output = (this - that - zoneDelta) / 864e5;
43 break; // 1000 * 60 * 60 * 24, negate dst
44 case 'week':
45 output = (this - that - zoneDelta) / 6048e5;
46 break; // 1000 * 60 * 60 * 24 * 7, negate dst
47 default:
48 output = this - that;
49 }
50
51 return asFloat ? output : absFloor(output);
52}
53
54function monthDiff(a, b) {
55 if (a.date() < b.date()) {
56 // end-of-month calculations work correct when the start month has more
57 // days than the end month.
58 return -monthDiff(b, a);
59 }
60 // difference in months
61 var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
62 // b is in (anchor - 1 month, anchor + 1 month)
63 anchor = a.clone().add(wholeMonthDiff, 'months'),
64 anchor2,
65 adjust;
66
67 if (b - anchor < 0) {
68 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
69 // linear across the month
70 adjust = (b - anchor) / (anchor - anchor2);
71 } else {
72 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
73 // linear across the month
74 adjust = (b - anchor) / (anchor2 - anchor);
75 }
76
77 //check for negative zero, return zero if negative zero
78 return -(wholeMonthDiff + adjust) || 0;
79}