1 | (function(){d3.time = {}; |
---|
2 | |
---|
3 | var d3_time = Date; |
---|
4 | d3.time.format = function(template) { |
---|
5 | var n = template.length; |
---|
6 | |
---|
7 | function format(date) { |
---|
8 | var string = [], |
---|
9 | i = -1, |
---|
10 | j = 0, |
---|
11 | c, |
---|
12 | f; |
---|
13 | while (++i < n) { |
---|
14 | if (template.charCodeAt(i) == 37) { |
---|
15 | string.push( |
---|
16 | template.substring(j, i), |
---|
17 | (f = d3_time_formats[c = template.charAt(++i)]) |
---|
18 | ? f(date) : c); |
---|
19 | j = i + 1; |
---|
20 | } |
---|
21 | } |
---|
22 | string.push(template.substring(j, i)); |
---|
23 | return string.join(""); |
---|
24 | } |
---|
25 | |
---|
26 | format.parse = function(string) { |
---|
27 | var date = new d3_time(1900, 0, 1), |
---|
28 | i = d3_time_parse(date, template, string, 0); |
---|
29 | if (i != string.length) return null; |
---|
30 | if (date.hour12) { |
---|
31 | var hours = date.getHours() % 12; |
---|
32 | date.setHours(date.hour12pm ? hours + 12 : hours); |
---|
33 | } |
---|
34 | delete date.hour12; |
---|
35 | delete date.hour12pm; |
---|
36 | return date; |
---|
37 | }; |
---|
38 | |
---|
39 | format.toString = function() { |
---|
40 | return template; |
---|
41 | }; |
---|
42 | |
---|
43 | return format; |
---|
44 | }; |
---|
45 | |
---|
46 | function d3_time_parse(date, template, string, j) { |
---|
47 | var c, |
---|
48 | p, |
---|
49 | i = 0, |
---|
50 | n = template.length, |
---|
51 | m = string.length; |
---|
52 | while (i < n) { |
---|
53 | if (j >= m) return -1; |
---|
54 | c = template.charCodeAt(i++); |
---|
55 | if (c == 37) { |
---|
56 | p = d3_time_parsers[template.charAt(i++)]; |
---|
57 | if (!p || ((j = p(date, string, j)) < 0)) return -1; |
---|
58 | } else if (c != string.charCodeAt(j++)) { |
---|
59 | return -1; |
---|
60 | } |
---|
61 | } |
---|
62 | return j; |
---|
63 | } |
---|
64 | |
---|
65 | var d3_time_zfill2 = d3.format("02d"), |
---|
66 | d3_time_zfill3 = d3.format("03d"), |
---|
67 | d3_time_zfill4 = d3.format("04d"), |
---|
68 | d3_time_sfill2 = d3.format("2d"); |
---|
69 | |
---|
70 | var d3_time_formats = { |
---|
71 | a: function(d) { return d3_time_weekdays[d.getDay()].substring(0, 3); }, |
---|
72 | A: function(d) { return d3_time_weekdays[d.getDay()]; }, |
---|
73 | b: function(d) { return d3_time_months[d.getMonth()].substring(0, 3); }, |
---|
74 | B: function(d) { return d3_time_months[d.getMonth()]; }, |
---|
75 | c: d3.time.format("%a %b %e %H:%M:%S %Y"), |
---|
76 | d: function(d) { return d3_time_zfill2(d.getDate()); }, |
---|
77 | e: function(d) { return d3_time_sfill2(d.getDate()); }, |
---|
78 | H: function(d) { return d3_time_zfill2(d.getHours()); }, |
---|
79 | I: function(d) { return d3_time_zfill2(d.getHours() % 12 || 12); }, |
---|
80 | j: d3_time_dayOfYear, |
---|
81 | m: function(d) { return d3_time_zfill2(d.getMonth() + 1); }, |
---|
82 | M: function(d) { return d3_time_zfill2(d.getMinutes()); }, |
---|
83 | p: function(d) { return d.getHours() >= 12 ? "PM" : "AM"; }, |
---|
84 | S: function(d) { return d3_time_zfill2(d.getSeconds()); }, |
---|
85 | U: d3_time_weekNumberSunday, |
---|
86 | w: function(d) { return d.getDay(); }, |
---|
87 | W: d3_time_weekNumberMonday, |
---|
88 | x: d3.time.format("%m/%d/%y"), |
---|
89 | X: d3.time.format("%H:%M:%S"), |
---|
90 | y: function(d) { return d3_time_zfill2(d.getFullYear() % 100); }, |
---|
91 | Y: function(d) { return d3_time_zfill4(d.getFullYear() % 10000); }, |
---|
92 | Z: d3_time_zone, |
---|
93 | "%": function(d) { return "%"; } |
---|
94 | }; |
---|
95 | |
---|
96 | var d3_time_parsers = { |
---|
97 | a: d3_time_parseWeekdayAbbrev, |
---|
98 | A: d3_time_parseWeekday, |
---|
99 | b: d3_time_parseMonthAbbrev, |
---|
100 | B: d3_time_parseMonth, |
---|
101 | c: d3_time_parseLocaleFull, |
---|
102 | d: d3_time_parseDay, |
---|
103 | e: d3_time_parseDay, |
---|
104 | H: d3_time_parseHour24, |
---|
105 | I: d3_time_parseHour12, |
---|
106 | // j: function(d, s, i) { /*TODO day of year [001,366] */ return i; }, |
---|
107 | m: d3_time_parseMonthNumber, |
---|
108 | M: d3_time_parseMinutes, |
---|
109 | p: d3_time_parseAmPm, |
---|
110 | S: d3_time_parseSeconds, |
---|
111 | // U: function(d, s, i) { /*TODO week number (sunday) [00,53] */ return i; }, |
---|
112 | // w: function(d, s, i) { /*TODO weekday [0,6] */ return i; }, |
---|
113 | // W: function(d, s, i) { /*TODO week number (monday) [00,53] */ return i; }, |
---|
114 | x: d3_time_parseLocaleDate, |
---|
115 | X: d3_time_parseLocaleTime, |
---|
116 | y: d3_time_parseYear, |
---|
117 | Y: d3_time_parseFullYear |
---|
118 | // , |
---|
119 | // Z: function(d, s, i) { /*TODO time zone */ return i; }, |
---|
120 | // "%": function(d, s, i) { /*TODO literal % */ return i; } |
---|
121 | }; |
---|
122 | |
---|
123 | // Note: weekday is validated, but does not set the date. |
---|
124 | function d3_time_parseWeekdayAbbrev(date, string, i) { |
---|
125 | return string.substring(i, i += 3).toLowerCase() in d3_time_weekdayAbbrevLookup ? i : -1; |
---|
126 | } |
---|
127 | |
---|
128 | var d3_time_weekdayAbbrevLookup = { |
---|
129 | sun: 3, |
---|
130 | mon: 3, |
---|
131 | tue: 3, |
---|
132 | wed: 3, |
---|
133 | thu: 3, |
---|
134 | fri: 3, |
---|
135 | sat: 3 |
---|
136 | }; |
---|
137 | |
---|
138 | // Note: weekday is validated, but does not set the date. |
---|
139 | function d3_time_parseWeekday(date, string, i) { |
---|
140 | d3_time_weekdayRe.lastIndex = 0; |
---|
141 | var n = d3_time_weekdayRe.exec(string.substring(i, i + 10)); |
---|
142 | return n ? i += n[0].length : -1; |
---|
143 | } |
---|
144 | |
---|
145 | var d3_time_weekdayRe = /^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/ig; |
---|
146 | |
---|
147 | var d3_time_weekdays = [ |
---|
148 | "Sunday", |
---|
149 | "Monday", |
---|
150 | "Tuesday", |
---|
151 | "Wednesday", |
---|
152 | "Thursday", |
---|
153 | "Friday", |
---|
154 | "Saturday" |
---|
155 | ]; |
---|
156 | |
---|
157 | function d3_time_parseMonthAbbrev(date, string, i) { |
---|
158 | var n = d3_time_monthAbbrevLookup[string.substring(i, i += 3).toLowerCase()]; |
---|
159 | return n == null ? -1 : (date.setMonth(n), i); |
---|
160 | } |
---|
161 | |
---|
162 | var d3_time_monthAbbrevLookup = { |
---|
163 | jan: 0, |
---|
164 | feb: 1, |
---|
165 | mar: 2, |
---|
166 | apr: 3, |
---|
167 | may: 4, |
---|
168 | jun: 5, |
---|
169 | jul: 6, |
---|
170 | aug: 7, |
---|
171 | sep: 8, |
---|
172 | oct: 9, |
---|
173 | nov: 10, |
---|
174 | dec: 11 |
---|
175 | }; |
---|
176 | |
---|
177 | function d3_time_parseMonth(date, string, i) { |
---|
178 | d3_time_monthRe.lastIndex = 0; |
---|
179 | var n = d3_time_monthRe.exec(string.substring(i, i + 12)); |
---|
180 | return n ? (date.setMonth(d3_time_monthLookup[n[0].toLowerCase()]), i += n[0].length) : -1; |
---|
181 | } |
---|
182 | |
---|
183 | var d3_time_monthRe = /^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig; |
---|
184 | |
---|
185 | var d3_time_monthLookup = { |
---|
186 | january: 0, |
---|
187 | february: 1, |
---|
188 | march: 2, |
---|
189 | april: 3, |
---|
190 | may: 4, |
---|
191 | june: 5, |
---|
192 | july: 6, |
---|
193 | august: 7, |
---|
194 | september: 8, |
---|
195 | october: 9, |
---|
196 | november: 10, |
---|
197 | december: 11 |
---|
198 | }; |
---|
199 | |
---|
200 | var d3_time_months = [ |
---|
201 | "January", |
---|
202 | "February", |
---|
203 | "March", |
---|
204 | "April", |
---|
205 | "May", |
---|
206 | "June", |
---|
207 | "July", |
---|
208 | "August", |
---|
209 | "September", |
---|
210 | "October", |
---|
211 | "November", |
---|
212 | "December" |
---|
213 | ]; |
---|
214 | |
---|
215 | function d3_time_parseLocaleFull(date, string, i) { |
---|
216 | return d3_time_parse(date, d3_time_formats.c.toString(), string, i); |
---|
217 | } |
---|
218 | |
---|
219 | function d3_time_parseLocaleDate(date, string, i) { |
---|
220 | return d3_time_parse(date, d3_time_formats.x.toString(), string, i); |
---|
221 | } |
---|
222 | |
---|
223 | function d3_time_parseLocaleTime(date, string, i) { |
---|
224 | return d3_time_parse(date, d3_time_formats.X.toString(), string, i); |
---|
225 | } |
---|
226 | |
---|
227 | function d3_time_parseFullYear(date, string, i) { |
---|
228 | d3_time_numberRe.lastIndex = 0; |
---|
229 | var n = d3_time_numberRe.exec(string.substring(i, i + 4)); |
---|
230 | return n ? (date.setFullYear(n[0]), i += n[0].length) : -1; |
---|
231 | } |
---|
232 | |
---|
233 | function d3_time_parseYear(date, string, i) { |
---|
234 | d3_time_numberRe.lastIndex = 0; |
---|
235 | var n = d3_time_numberRe.exec(string.substring(i, i + 2)); |
---|
236 | return n ? (date.setFullYear(d3_time_century() + +n[0]), i += n[0].length) : -1; |
---|
237 | } |
---|
238 | |
---|
239 | function d3_time_century() { |
---|
240 | return ~~(new Date().getFullYear() / 1000) * 1000; |
---|
241 | } |
---|
242 | |
---|
243 | function d3_time_parseMonthNumber(date, string, i) { |
---|
244 | d3_time_numberRe.lastIndex = 0; |
---|
245 | var n = d3_time_numberRe.exec(string.substring(i, i + 2)); |
---|
246 | return n ? (date.setMonth(n[0] - 1), i += n[0].length) : -1; |
---|
247 | } |
---|
248 | |
---|
249 | function d3_time_parseDay(date, string, i) { |
---|
250 | d3_time_numberRe.lastIndex = 0; |
---|
251 | var n = d3_time_numberRe.exec(string.substring(i, i + 2)); |
---|
252 | return n ? (date.setDate(+n[0]), i += n[0].length) : -1; |
---|
253 | } |
---|
254 | |
---|
255 | // Note: we don't validate that the hour is in the range [0,23]. |
---|
256 | function d3_time_parseHour24(date, string, i) { |
---|
257 | d3_time_numberRe.lastIndex = 0; |
---|
258 | var n = d3_time_numberRe.exec(string.substring(i, i + 2)); |
---|
259 | return n ? (date.setHours(+n[0]), i += n[0].length) : -1; |
---|
260 | } |
---|
261 | |
---|
262 | // Note: we don't validate that the hour is in the range [1,12]. |
---|
263 | function d3_time_parseHour12(date, string, i) { |
---|
264 | date.hour12 = true; |
---|
265 | return d3_time_parseHour24(date, string, i); |
---|
266 | } |
---|
267 | |
---|
268 | function d3_time_parseMinutes(date, string, i) { |
---|
269 | d3_time_numberRe.lastIndex = 0; |
---|
270 | var n = d3_time_numberRe.exec(string.substring(i, i + 2)); |
---|
271 | return n ? (date.setMinutes(+n[0]), i += n[0].length) : -1; |
---|
272 | } |
---|
273 | |
---|
274 | function d3_time_parseSeconds(date, string, i) { |
---|
275 | d3_time_numberRe.lastIndex = 0; |
---|
276 | var n = d3_time_numberRe.exec(string.substring(i, i + 2)); |
---|
277 | return n ? (date.setSeconds(+n[0]), i += n[0].length) : -1; |
---|
278 | } |
---|
279 | |
---|
280 | // Note: we don't look at the next directive. |
---|
281 | var d3_time_numberRe = /\s*\d+/; |
---|
282 | |
---|
283 | function d3_time_parseAmPm(date, string, i) { |
---|
284 | var n = d3_time_amPmLookup[string.substring(i, i += 2).toLowerCase()]; |
---|
285 | return n == null ? -1 : (date.hour12pm = n, i); |
---|
286 | } |
---|
287 | |
---|
288 | var d3_time_amPmLookup = { |
---|
289 | am: 0, |
---|
290 | pm: 1 |
---|
291 | }; |
---|
292 | |
---|
293 | function d3_time_year(d) { |
---|
294 | return new d3_time(d.getFullYear(), 0, 1); |
---|
295 | } |
---|
296 | |
---|
297 | function d3_time_dayOfYear(d) { |
---|
298 | return d3_time_zfill3(1 + ~~((d - d3_time_year(d)) / 864e5)); |
---|
299 | } |
---|
300 | |
---|
301 | function d3_time_weekNumberSunday(d) { |
---|
302 | var d0 = d3_time_year(d); |
---|
303 | return d3_time_zfill2(~~(((d - d0) / 864e5 + d0.getDay()) / 7)); |
---|
304 | } |
---|
305 | |
---|
306 | function d3_time_weekNumberMonday(d) { |
---|
307 | var d0 = d3_time_year(d); |
---|
308 | return d3_time_zfill2(~~(((d - d0) / 864e5 + (d0.getDay() + 6) % 7) / 7)); |
---|
309 | } |
---|
310 | |
---|
311 | // TODO table of time zone offset names? |
---|
312 | function d3_time_zone(d) { |
---|
313 | var z = d.getTimezoneOffset(), |
---|
314 | zs = z > 0 ? "-" : "+", |
---|
315 | zh = ~~(Math.abs(z) / 60), |
---|
316 | zm = Math.abs(z) % 60; |
---|
317 | return zs + d3_time_zfill2(zh) + d3_time_zfill2(zm); |
---|
318 | } |
---|
319 | d3.time.format.utc = function(template) { |
---|
320 | var local = d3.time.format(template); |
---|
321 | |
---|
322 | function format(date) { |
---|
323 | var utc = new d3_time_format_utc(); |
---|
324 | utc._ = date; |
---|
325 | return local(utc); |
---|
326 | } |
---|
327 | |
---|
328 | format.parse = function(string) { |
---|
329 | try { |
---|
330 | d3_time = d3_time_format_utc; |
---|
331 | var date = local.parse(string); |
---|
332 | return date && date._; |
---|
333 | } finally { |
---|
334 | d3_time = Date; |
---|
335 | } |
---|
336 | }; |
---|
337 | |
---|
338 | format.toString = local.toString; |
---|
339 | |
---|
340 | return format; |
---|
341 | }; |
---|
342 | |
---|
343 | function d3_time_format_utc() { |
---|
344 | this._ = new Date(Date.UTC.apply(this, arguments)); |
---|
345 | } |
---|
346 | |
---|
347 | d3_time_format_utc.prototype = { |
---|
348 | getDate: function() { return this._.getUTCDate(); }, |
---|
349 | getDay: function() { return this._.getUTCDay(); }, |
---|
350 | getFullYear: function() { return this._.getUTCFullYear(); }, |
---|
351 | getHours: function() { return this._.getUTCHours(); }, |
---|
352 | getMilliseconds: function() { return this._.getUTCMilliseconds(); }, |
---|
353 | getMinutes: function() { return this._.getUTCMinutes(); }, |
---|
354 | getMonth: function() { return this._.getUTCMonth(); }, |
---|
355 | getSeconds: function() { return this._.getUTCSeconds(); }, |
---|
356 | getTimezoneOffset: function() { return 0; }, |
---|
357 | valueOf: function() { return this._.getTime(); }, |
---|
358 | setDate: function(x) { this._.setUTCDate(x); }, |
---|
359 | setDay: function(x) { this._.setUTCDay(x); }, |
---|
360 | setFullYear: function(x) { this._.setUTCFullYear(x); }, |
---|
361 | setHours: function(x) { this._.setUTCHours(x); }, |
---|
362 | setMilliseconds: function(x) { this._.setUTCMilliseconds(x); }, |
---|
363 | setMinutes: function(x) { this._.setUTCMinutes(x); }, |
---|
364 | setMonth: function(x) { this._.setUTCMonth(x); }, |
---|
365 | setSeconds: function(x) { this._.setUTCSeconds(x); } |
---|
366 | }; |
---|
367 | d3.time.format.iso = d3.time.format.utc("%Y-%m-%dT%H:%M:%SZ"); |
---|
368 | function d3_time_range(floor, step, number) { |
---|
369 | return function(t0, t1, dt) { |
---|
370 | var time = floor(t0), times = []; |
---|
371 | if (time < t0) step(time); |
---|
372 | if (dt > 1) { |
---|
373 | while (time < t1) { |
---|
374 | var date = new Date(+time); |
---|
375 | if (!(number(date) % dt)) times.push(date); |
---|
376 | step(time); |
---|
377 | } |
---|
378 | } else { |
---|
379 | while (time < t1) times.push(new Date(+time)), step(time); |
---|
380 | } |
---|
381 | return times; |
---|
382 | }; |
---|
383 | } |
---|
384 | d3.time.second = function(date) { |
---|
385 | return new Date(~~(date / 1e3) * 1e3); |
---|
386 | }; |
---|
387 | |
---|
388 | d3.time.second.utc = d3.time.second; |
---|
389 | d3.time.seconds = d3_time_range(d3.time.second, function(date) { |
---|
390 | date.setTime(date.getTime() + 1e3); |
---|
391 | }, function(date) { |
---|
392 | return date.getSeconds(); |
---|
393 | }); |
---|
394 | |
---|
395 | d3.time.seconds.utc = d3.time.seconds; |
---|
396 | d3.time.minute = function(date) { |
---|
397 | return new Date(~~(date / 6e4) * 6e4); |
---|
398 | }; |
---|
399 | |
---|
400 | d3.time.minute.utc = d3.time.minute;d3.time.minutes = d3_time_range(d3.time.minute, d3_time_minutesStep, function(date) { |
---|
401 | return date.getMinutes(); |
---|
402 | }); |
---|
403 | |
---|
404 | d3.time.minutes.utc = d3_time_range(d3.time.minute, d3_time_minutesStep, function(date) { |
---|
405 | return date.getUTCMinutes(); |
---|
406 | }); |
---|
407 | |
---|
408 | function d3_time_minutesStep(date) { |
---|
409 | date.setTime(date.getTime() + 6e4); // assumes no leap seconds |
---|
410 | } |
---|
411 | d3.time.hour = function(date) { |
---|
412 | var offset = date.getTimezoneOffset() / 60; |
---|
413 | return new Date((~~(date / 36e5 - offset) + offset) * 36e5); |
---|
414 | }; |
---|
415 | |
---|
416 | d3.time.hour.utc = function(date) { |
---|
417 | return new Date(~~(date / 36e5) * 36e5); |
---|
418 | }; |
---|
419 | d3.time.hours = d3_time_range(d3.time.hour, d3_time_hoursStep, function(date) { |
---|
420 | return date.getHours(); |
---|
421 | }); |
---|
422 | |
---|
423 | d3.time.hours.utc = d3_time_range(d3.time.hour.utc, d3_time_hoursStep, function(date) { |
---|
424 | return date.getUTCHours(); |
---|
425 | }); |
---|
426 | |
---|
427 | function d3_time_hoursStep(date) { |
---|
428 | date.setTime(date.getTime() + 36e5); |
---|
429 | } |
---|
430 | d3.time.day = function(date) { |
---|
431 | return new Date(date.getFullYear(), date.getMonth(), date.getDate()); |
---|
432 | }; |
---|
433 | |
---|
434 | d3.time.day.utc = function(date) { |
---|
435 | return new Date(~~(date / 864e5) * 864e5); |
---|
436 | }; |
---|
437 | d3.time.days = d3_time_range(d3.time.day, function(date) { |
---|
438 | date.setDate(date.getDate() + 1); |
---|
439 | }, function(date) { |
---|
440 | return date.getDate() - 1; |
---|
441 | }); |
---|
442 | |
---|
443 | d3.time.days.utc = d3_time_range(d3.time.day.utc, function(date) { |
---|
444 | date.setUTCDate(date.getUTCDate() + 1); |
---|
445 | }, function(date) { |
---|
446 | return date.getUTCDate() - 1; |
---|
447 | }); |
---|
448 | d3.time.week = function(date) { |
---|
449 | (date = d3.time.day(date)).setDate(date.getDate() - date.getDay()); |
---|
450 | return date; |
---|
451 | }; |
---|
452 | |
---|
453 | d3.time.week.utc = function(date) { |
---|
454 | (date = d3.time.day.utc(date)).setUTCDate(date.getUTCDate() - date.getUTCDay()); |
---|
455 | return date; |
---|
456 | }; |
---|
457 | d3.time.weeks = d3_time_range(d3.time.week, function(date) { |
---|
458 | date.setDate(date.getDate() + 7); |
---|
459 | }, function(date) { |
---|
460 | return ~~((date - new Date(date.getFullYear(), 0, 1)) / 6048e5); |
---|
461 | }); |
---|
462 | |
---|
463 | d3.time.weeks.utc = d3_time_range(d3.time.week.utc, function(date) { |
---|
464 | date.setUTCDate(date.getUTCDate() + 7); |
---|
465 | }, function(date) { |
---|
466 | return ~~((date - Date.UTC(date.getUTCFullYear(), 0, 1)) / 6048e5); |
---|
467 | }); |
---|
468 | d3.time.month = function(date) { |
---|
469 | return new Date(date.getFullYear(), date.getMonth(), 1); |
---|
470 | }; |
---|
471 | |
---|
472 | d3.time.month.utc = function(date) { |
---|
473 | return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1)); |
---|
474 | }; |
---|
475 | d3.time.months = d3_time_range(d3.time.month, function(date) { |
---|
476 | date.setMonth(date.getMonth() + 1); |
---|
477 | }, function(date) { |
---|
478 | return date.getMonth(); |
---|
479 | }); |
---|
480 | |
---|
481 | d3.time.months.utc = d3_time_range(d3.time.month.utc, function(date) { |
---|
482 | date.setUTCMonth(date.getUTCMonth() + 1); |
---|
483 | }, function(date) { |
---|
484 | return date.getUTCMonth(); |
---|
485 | }); |
---|
486 | d3.time.year = function(date) { |
---|
487 | return new Date(date.getFullYear(), 0, 1); |
---|
488 | }; |
---|
489 | |
---|
490 | d3.time.year.utc = function(date) { |
---|
491 | return new Date(Date.UTC(date.getUTCFullYear(), 0, 1)); |
---|
492 | }; |
---|
493 | d3.time.years = d3_time_range(d3.time.year, function(date) { |
---|
494 | date.setFullYear(date.getFullYear() + 1); |
---|
495 | }, function(date) { |
---|
496 | return date.getFullYear(); |
---|
497 | }); |
---|
498 | |
---|
499 | d3.time.years.utc = d3_time_range(d3.time.year.utc, function(date) { |
---|
500 | date.setUTCFullYear(date.getUTCFullYear() + 1); |
---|
501 | }, function(date) { |
---|
502 | return date.getUTCFullYear(); |
---|
503 | }); |
---|
504 | // TODO nice |
---|
505 | function d3_time_scale(methods, format) { |
---|
506 | var linear = d3.scale.linear(); |
---|
507 | |
---|
508 | function scale(x) { |
---|
509 | return linear(x); |
---|
510 | } |
---|
511 | |
---|
512 | scale.invert = function(x) { |
---|
513 | return d3_time_scaleDate(linear.invert(x)); |
---|
514 | }; |
---|
515 | |
---|
516 | scale.domain = function(x) { |
---|
517 | if (!arguments.length) return linear.domain().map(d3_time_scaleDate); |
---|
518 | linear.domain(x); |
---|
519 | return scale; |
---|
520 | }; |
---|
521 | |
---|
522 | scale.ticks = function(m, k) { |
---|
523 | var extent = d3_time_scaleExtent(scale.domain()); |
---|
524 | if (typeof m !== "function") { |
---|
525 | var span = extent[1] - extent[0], |
---|
526 | target = span / m, |
---|
527 | i = d3.bisect(d3_time_scaleSteps, target, 1, d3_time_scaleSteps.length - 1); |
---|
528 | if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i; |
---|
529 | m = methods[i]; |
---|
530 | k = m[1]; |
---|
531 | m = m[0]; |
---|
532 | } |
---|
533 | return m(extent[0], extent[1], k); |
---|
534 | }; |
---|
535 | |
---|
536 | scale.tickFormat = function() { |
---|
537 | return format; |
---|
538 | }; |
---|
539 | |
---|
540 | // TOOD expose d3_scale_linear_rebind? |
---|
541 | scale.range = d3.rebind(scale, linear.range); |
---|
542 | scale.rangeRound = d3.rebind(scale, linear.rangeRound); |
---|
543 | scale.interpolate = d3.rebind(scale, linear.interpolate); |
---|
544 | scale.clamp = d3.rebind(scale, linear.clamp); |
---|
545 | |
---|
546 | return scale; |
---|
547 | } |
---|
548 | |
---|
549 | // TODO expose d3_scaleExtent? |
---|
550 | function d3_time_scaleExtent(domain) { |
---|
551 | var start = domain[0], stop = domain[domain.length - 1]; |
---|
552 | return start < stop ? [start, stop] : [stop, start]; |
---|
553 | } |
---|
554 | |
---|
555 | function d3_time_scaleDate(t) { |
---|
556 | return new Date(t); |
---|
557 | } |
---|
558 | |
---|
559 | function d3_time_scaleFormat(formats) { |
---|
560 | return function(date) { |
---|
561 | var i = formats.length - 1, f = formats[i]; |
---|
562 | while (!f[1](date)) f = formats[--i]; |
---|
563 | return f[0](date); |
---|
564 | }; |
---|
565 | } |
---|
566 | |
---|
567 | var d3_time_scaleSteps = [ |
---|
568 | 1e3, // 1-second |
---|
569 | 5e3, // 5-second |
---|
570 | 15e3, // 15-second |
---|
571 | 3e4, // 30-second |
---|
572 | 6e4, // 1-minute |
---|
573 | 3e5, // 5-minute |
---|
574 | 9e5, // 15-minute |
---|
575 | 18e5, // 30-minute |
---|
576 | 36e5, // 1-hour |
---|
577 | 108e5, // 3-hour |
---|
578 | 216e5, // 6-hour |
---|
579 | 432e5, // 12-hour |
---|
580 | 864e5, // 1-day |
---|
581 | 1728e5, // 2-day |
---|
582 | 6048e5, // 1-week |
---|
583 | 1728e6, // 1-month |
---|
584 | 7776e6, // 3-month |
---|
585 | 31536e6 // 1-year |
---|
586 | ]; |
---|
587 | |
---|
588 | var d3_time_scaleLocalMethods = [ |
---|
589 | [d3.time.seconds, 1], |
---|
590 | [d3.time.seconds, 5], |
---|
591 | [d3.time.seconds, 15], |
---|
592 | [d3.time.seconds, 30], |
---|
593 | [d3.time.minutes, 1], |
---|
594 | [d3.time.minutes, 5], |
---|
595 | [d3.time.minutes, 15], |
---|
596 | [d3.time.minutes, 30], |
---|
597 | [d3.time.hours, 1], |
---|
598 | [d3.time.hours, 3], |
---|
599 | [d3.time.hours, 6], |
---|
600 | [d3.time.hours, 12], |
---|
601 | [d3.time.days, 1], |
---|
602 | [d3.time.days, 2], |
---|
603 | [d3.time.weeks, 1], |
---|
604 | [d3.time.months, 1], |
---|
605 | [d3.time.months, 3], |
---|
606 | [d3.time.years, 1] |
---|
607 | ]; |
---|
608 | |
---|
609 | var d3_time_scaleLocalFormats = [ |
---|
610 | [d3.time.format("%Y"), function(d) { return true; }], |
---|
611 | [d3.time.format("%B"), function(d) { return d.getMonth(); }], |
---|
612 | [d3.time.format("%b %d"), function(d) { return d.getDate() != 1; }], |
---|
613 | [d3.time.format("%a %d"), function(d) { return d.getDay() && d.getDate() != 1; }], |
---|
614 | [d3.time.format("%I %p"), function(d) { return d.getHours(); }], |
---|
615 | [d3.time.format("%I:%M"), function(d) { return d.getMinutes(); }], |
---|
616 | [d3.time.format(":%S"), function(d) { return d.getSeconds() || d.getMilliseconds(); }] |
---|
617 | ]; |
---|
618 | |
---|
619 | var d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats); |
---|
620 | |
---|
621 | d3.time.scale = function() { |
---|
622 | return d3_time_scale(d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); |
---|
623 | }; |
---|
624 | var d3_time_scaleUTCMethods = [ |
---|
625 | [d3.time.seconds.utc, 1], |
---|
626 | [d3.time.seconds.utc, 5], |
---|
627 | [d3.time.seconds.utc, 15], |
---|
628 | [d3.time.seconds.utc, 30], |
---|
629 | [d3.time.minutes.utc, 1], |
---|
630 | [d3.time.minutes.utc, 5], |
---|
631 | [d3.time.minutes.utc, 15], |
---|
632 | [d3.time.minutes.utc, 30], |
---|
633 | [d3.time.hours.utc, 1], |
---|
634 | [d3.time.hours.utc, 3], |
---|
635 | [d3.time.hours.utc, 6], |
---|
636 | [d3.time.hours.utc, 12], |
---|
637 | [d3.time.days.utc, 1], |
---|
638 | [d3.time.days.utc, 2], |
---|
639 | [d3.time.weeks.utc, 1], |
---|
640 | [d3.time.months.utc, 1], |
---|
641 | [d3.time.months.utc, 3], |
---|
642 | [d3.time.years.utc, 1] |
---|
643 | ]; |
---|
644 | |
---|
645 | var d3_time_scaleUTCFormats = [ |
---|
646 | [d3.time.format.utc("%Y"), function(d) { return true; }], |
---|
647 | [d3.time.format.utc("%B"), function(d) { return d.getUTCMonth(); }], |
---|
648 | [d3.time.format.utc("%b %d"), function(d) { return d.getUTCDate() != 1; }], |
---|
649 | [d3.time.format.utc("%a %d"), function(d) { return d.getUTCDay() && d.getUTCDate() != 1; }], |
---|
650 | [d3.time.format.utc("%I %p"), function(d) { return d.getUTCHours(); }], |
---|
651 | [d3.time.format.utc("%I:%M"), function(d) { return d.getUTCMinutes(); }], |
---|
652 | [d3.time.format.utc(":%S"), function(d) { return d.getUTCSeconds() || d.getUTCMilliseconds(); }] |
---|
653 | ]; |
---|
654 | |
---|
655 | var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats); |
---|
656 | |
---|
657 | d3.time.scale.utc = function() { |
---|
658 | return d3_time_scale(d3_time_scaleUTCMethods, d3_time_scaleUTCFormat); |
---|
659 | }; |
---|
660 | })(); |
---|