|
1 // TODO nice |
|
2 function d3_time_scale(linear, methods, format) { |
|
3 |
|
4 function scale(x) { |
|
5 return linear(x); |
|
6 } |
|
7 |
|
8 scale.invert = function(x) { |
|
9 return d3_time_scaleDate(linear.invert(x)); |
|
10 }; |
|
11 |
|
12 scale.domain = function(x) { |
|
13 if (!arguments.length) return linear.domain().map(d3_time_scaleDate); |
|
14 linear.domain(x); |
|
15 return scale; |
|
16 }; |
|
17 |
|
18 scale.ticks = function(m, k) { |
|
19 var extent = d3_time_scaleExtent(scale.domain()); |
|
20 if (typeof m !== "function") { |
|
21 var span = extent[1] - extent[0], |
|
22 target = span / m, |
|
23 i = d3.bisect(d3_time_scaleSteps, target, 1, d3_time_scaleSteps.length - 1); |
|
24 if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i; |
|
25 m = methods[i]; |
|
26 k = m[1]; |
|
27 m = m[0]; |
|
28 } |
|
29 return m(extent[0], extent[1], k); |
|
30 }; |
|
31 |
|
32 scale.tickFormat = function() { |
|
33 return format; |
|
34 }; |
|
35 |
|
36 scale.copy = function() { |
|
37 return d3_time_scale(linear.copy(), methods, format); |
|
38 }; |
|
39 |
|
40 // TOOD expose d3_scale_linear_rebind? |
|
41 scale.range = d3.rebind(scale, linear.range); |
|
42 scale.rangeRound = d3.rebind(scale, linear.rangeRound); |
|
43 scale.interpolate = d3.rebind(scale, linear.interpolate); |
|
44 scale.clamp = d3.rebind(scale, linear.clamp); |
|
45 |
|
46 return scale; |
|
47 } |
|
48 |
|
49 // TODO expose d3_scaleExtent? |
|
50 function d3_time_scaleExtent(domain) { |
|
51 var start = domain[0], stop = domain[domain.length - 1]; |
|
52 return start < stop ? [start, stop] : [stop, start]; |
|
53 } |
|
54 |
|
55 function d3_time_scaleDate(t) { |
|
56 return new Date(t); |
|
57 } |
|
58 |
|
59 function d3_time_scaleFormat(formats) { |
|
60 return function(date) { |
|
61 var i = formats.length - 1, f = formats[i]; |
|
62 while (!f[1](date)) f = formats[--i]; |
|
63 return f[0](date); |
|
64 }; |
|
65 } |
|
66 |
|
67 var d3_time_scaleSteps = [ |
|
68 1e3, // 1-second |
|
69 5e3, // 5-second |
|
70 15e3, // 15-second |
|
71 3e4, // 30-second |
|
72 6e4, // 1-minute |
|
73 3e5, // 5-minute |
|
74 9e5, // 15-minute |
|
75 18e5, // 30-minute |
|
76 36e5, // 1-hour |
|
77 108e5, // 3-hour |
|
78 216e5, // 6-hour |
|
79 432e5, // 12-hour |
|
80 864e5, // 1-day |
|
81 1728e5, // 2-day |
|
82 6048e5, // 1-week |
|
83 1728e6, // 1-month |
|
84 7776e6, // 3-month |
|
85 31536e6 // 1-year |
|
86 ]; |
|
87 |
|
88 var d3_time_scaleLocalMethods = [ |
|
89 [d3.time.seconds, 1], |
|
90 [d3.time.seconds, 5], |
|
91 [d3.time.seconds, 15], |
|
92 [d3.time.seconds, 30], |
|
93 [d3.time.minutes, 1], |
|
94 [d3.time.minutes, 5], |
|
95 [d3.time.minutes, 15], |
|
96 [d3.time.minutes, 30], |
|
97 [d3.time.hours, 1], |
|
98 [d3.time.hours, 3], |
|
99 [d3.time.hours, 6], |
|
100 [d3.time.hours, 12], |
|
101 [d3.time.days, 1], |
|
102 [d3.time.days, 2], |
|
103 [d3.time.weeks, 1], |
|
104 [d3.time.months, 1], |
|
105 [d3.time.months, 3], |
|
106 [d3.time.years, 1] |
|
107 ]; |
|
108 |
|
109 var d3_time_scaleLocalFormats = [ |
|
110 [d3.time.format("%Y"), function(d) { return true; }], |
|
111 [d3.time.format("%B"), function(d) { return d.getMonth(); }], |
|
112 [d3.time.format("%b %d"), function(d) { return d.getDate() != 1; }], |
|
113 [d3.time.format("%a %d"), function(d) { return d.getDay() && d.getDate() != 1; }], |
|
114 [d3.time.format("%I %p"), function(d) { return d.getHours(); }], |
|
115 [d3.time.format("%I:%M"), function(d) { return d.getMinutes(); }], |
|
116 [d3.time.format(":%S"), function(d) { return d.getSeconds() || d.getMilliseconds(); }] |
|
117 ]; |
|
118 |
|
119 var d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats); |
|
120 |
|
121 d3.time.scale = function() { |
|
122 return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); |
|
123 }; |