|
9 | 9 | 'use strict'; |
10 | 10 |
|
11 | 11 | var isNumeric = require('fast-isnumeric'); |
12 | | -var ms2DateTime = require('../../lib').ms2DateTime; |
13 | | -var ONEDAY = require('../../constants/numerical').ONEDAY; |
| 12 | +var Lib = require('../../lib'); |
| 13 | +var ms2DateTime = Lib.ms2DateTime; |
| 14 | +var dateTime2ms = Lib.dateTime2ms; |
| 15 | +var constants = require('../../constants/numerical'); |
| 16 | +var ONEDAY = constants.ONEDAY; |
| 17 | +var ONEAVGMONTH = constants.ONEAVGMONTH; |
| 18 | +var ONEAVGYEAR = constants.ONEAVGYEAR; |
14 | 19 |
|
15 | 20 | module.exports = function alignPeriod(trace, ax, axLetter, vals) { |
16 | 21 | var alignment = trace[axLetter + 'periodalignment']; |
17 | | - if(!alignment || alignment === 'start') return vals; |
| 22 | + if(!alignment) return vals; |
18 | 23 |
|
19 | | - var dynamic = false; |
20 | 24 | var period = trace[axLetter + 'period']; |
21 | 25 | if(isNumeric(period)) { |
22 | | - period = +period; // milliseconds |
| 26 | + period = +period; |
23 | 27 | if(period <= 0) return vals; |
24 | 28 | } else if(typeof period === 'string' && period.charAt(0) === 'M') { |
25 | | - var v = +(period.substring(1)); |
26 | | - if(v > 0 && Math.round(v) === v) period = v; // positive integer months |
| 29 | + var n = +(period.substring(1)); |
| 30 | + if(n > 0 && Math.round(n) === n) period = n * ONEAVGMONTH; |
27 | 31 | else return vals; |
28 | | - |
29 | | - dynamic = true; |
30 | 32 | } |
31 | 33 |
|
32 | 34 | if(period > 0) { |
33 | | - var ratio = (alignment === 'end') ? 1 : 0.5; |
| 35 | + var calendar = ax.calendar; |
| 36 | + |
| 37 | + var isStart = 'start' === alignment; |
| 38 | + // var isMiddle = 'middle' === alignment; |
| 39 | + var isEnd = 'end' === alignment; |
| 40 | + |
| 41 | + var offset = (new Date()).getTimezoneOffset() * 60000; |
| 42 | + var period0 = trace[axLetter + 'period0']; |
| 43 | + var base = (dateTime2ms(period0, calendar) || 0) - offset; |
34 | 44 |
|
35 | 45 | var len = vals.length; |
36 | 46 | for(var i = 0; i < len; i++) { |
37 | | - var delta; |
38 | | - |
39 | | - if(dynamic) { |
40 | | - var dateStr = ms2DateTime(vals[i], 0, ax.calendar); |
41 | | - var d = new Date(dateStr); |
42 | | - var year = d.getFullYear(); |
43 | | - var month = d.getMonth() + 1; |
44 | | - |
45 | | - var totalDaysInMonths = 0; |
46 | | - for(var k = 0; k < period; k++) { |
47 | | - month += 1; |
48 | | - if(month > 12) { |
49 | | - month = 1; |
50 | | - year++; |
51 | | - } |
| 47 | + var v = vals[i] - base; |
| 48 | + |
| 49 | + var dateStr = ms2DateTime(v, 0, calendar); |
| 50 | + var O = new Date(dateStr); |
| 51 | + var year = O.getFullYear(); |
| 52 | + var month = O.getMonth(); |
| 53 | + var day = O.getDate(); |
| 54 | + |
| 55 | + var newD; |
| 56 | + var startTime; |
| 57 | + var endTime; |
52 | 58 |
|
53 | | - var monthDays = ( |
54 | | - new Date(year, month, 0) |
55 | | - ).getDate(); |
| 59 | + var nYears = Math.floor(period / ONEAVGYEAR); |
| 60 | + var nMonths = Math.floor(period / ONEAVGMONTH) % 12; |
| 61 | + var nDays = Math.floor((period - nYears * ONEAVGYEAR - nMonths * ONEAVGMONTH) / ONEDAY); |
| 62 | + if(nYears && nMonths) nDays = 0; |
56 | 63 |
|
57 | | - totalDaysInMonths += monthDays; |
| 64 | + var y1 = year + nYears; |
| 65 | + var m1 = month + nMonths; |
| 66 | + var d1 = day + nDays; |
| 67 | + if(nDays || nMonths || nYears) { |
| 68 | + if(nDays) { |
| 69 | + startTime = (new Date(year, month, day)).getTime(); |
| 70 | + var monthDays = new Date(y1, m1, 0).getDate(); |
| 71 | + if(d1 > monthDays) { |
| 72 | + d1 -= monthDays; |
| 73 | + m1 += 1; |
| 74 | + if(m1 > 11) { |
| 75 | + m1 -= 12; |
| 76 | + y1 += 1; |
| 77 | + } |
| 78 | + } |
| 79 | + endTime = (new Date(y1, m1, d1)).getTime(); |
| 80 | + } else if(nMonths) { |
| 81 | + startTime = (new Date(year, nYears ? month : roundMonth(month, nMonths))).getTime(); |
| 82 | + if(m1 > 11) { |
| 83 | + m1 -= 12; |
| 84 | + y1 += 1; |
| 85 | + } |
| 86 | + endTime = (new Date(y1, nYears ? m1 : roundMonth(m1, nMonths))).getTime(); |
| 87 | + } else { |
| 88 | + startTime = (new Date(year, 0)).getTime(); |
| 89 | + endTime = (new Date(y1, 0)).getTime(); |
58 | 90 | } |
59 | 91 |
|
60 | | - delta = ONEDAY * totalDaysInMonths; // convert to ms |
61 | | - } else { |
62 | | - delta = period; |
| 92 | + newD = new Date( |
| 93 | + isStart ? startTime : |
| 94 | + isEnd ? endTime : |
| 95 | + (startTime + endTime) / 2 |
| 96 | + ); |
63 | 97 | } |
64 | 98 |
|
65 | | - vals[i] += ratio * delta; |
| 99 | + if(newD) { |
| 100 | + vals[i] = newD.getTime() + base; |
| 101 | + } |
66 | 102 | } |
67 | 103 | } |
68 | 104 | return vals; |
69 | 105 | }; |
| 106 | + |
| 107 | +var monthSteps = [2, 3, 4, 6]; |
| 108 | + |
| 109 | +function roundMonth(month, step) { |
| 110 | + return (monthSteps.indexOf(step) === -1) ? month : Math.floor(month / step) * step; |
| 111 | +} |
0 commit comments