-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathalign_period.js
93 lines (76 loc) · 2.79 KB
/
align_period.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
'use strict';
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
var dateTime2ms = Lib.dateTime2ms;
var incrementMonth = Lib.incrementMonth;
var constants = require('../../constants/numerical');
var ONEAVGMONTH = constants.ONEAVGMONTH;
module.exports = function alignPeriod(trace, ax, axLetter, vals) {
if(ax.type !== 'date') return {vals: vals};
var alignment = trace[axLetter + 'periodalignment'];
if(!alignment) return {vals: vals};
var period = trace[axLetter + 'period'];
var mPeriod;
if(isNumeric(period)) {
period = +period;
if(period <= 0) return {vals: vals};
} else if(typeof period === 'string' && period.charAt(0) === 'M') {
var n = +(period.substring(1));
if(n > 0 && Math.round(n) === n) {
mPeriod = n;
} else return {vals: vals};
}
var calendar = ax.calendar;
var isStart = 'start' === alignment;
// var isMiddle = 'middle' === alignment;
var isEnd = 'end' === alignment;
var period0 = trace[axLetter + 'period0'];
var base = dateTime2ms(period0, calendar) || 0;
var newVals = [];
var starts = [];
var ends = [];
var len = vals.length;
for(var i = 0; i < len; i++) {
var v = vals[i];
var nEstimated, startTime, endTime;
if(mPeriod) {
// guess at how many periods away from base we are
nEstimated = Math.round((v - base) / (mPeriod * ONEAVGMONTH));
endTime = incrementMonth(base, mPeriod * nEstimated, calendar);
// iterate to get the exact bounds before and after v
// there may be ways to make this faster, but most of the time
// we'll only execute each loop zero or one time.
while(endTime > v) {
endTime = incrementMonth(endTime, -mPeriod, calendar);
}
while(endTime <= v) {
endTime = incrementMonth(endTime, mPeriod, calendar);
}
// now we know endTime is the boundary immediately after v
// so startTime is obtained by incrementing backward one period.
startTime = incrementMonth(endTime, -mPeriod, calendar);
} else { // case of ms
nEstimated = Math.round((v - base) / period);
endTime = base + nEstimated * period;
while(endTime > v) {
endTime -= period;
}
while(endTime <= v) {
endTime += period;
}
startTime = endTime - period;
}
newVals[i] = (
isStart ? startTime :
isEnd ? endTime :
(startTime + endTime) / 2
);
starts[i] = startTime;
ends[i] = endTime;
}
return {
vals: newVals,
starts: starts,
ends: ends
};
};