| import "../arrays/map"; | |
| import "../format/requote"; | |
| import "../math/abs"; | |
| import "../time/day"; | |
| import "../time/time"; | |
| import "../time/week"; | |
| import "../time/interval"; | |
| function d3_locale_timeFormat(locale) { | |
| var locale_dateTime = locale.dateTime, | |
| locale_date = locale.date, | |
| locale_time = locale.time, | |
| locale_periods = locale.periods, | |
| locale_days = locale.days, | |
| locale_shortDays = locale.shortDays, | |
| locale_months = locale.months, | |
| locale_shortMonths = locale.shortMonths; | |
| function d3_time_format(template) { | |
| var n = template.length; | |
| function format(date) { | |
| var string = [], | |
| i = -1, | |
| j = 0, | |
| c, | |
| p, | |
| f; | |
| while (++i < n) { | |
| if (template.charCodeAt(i) === 37) { | |
| string.push(template.substring(j, i)); | |
| if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); | |
| if (f = d3_time_formats[c]) c = f(date, p == null ? (c === "e" ? " " : "0") : p); | |
| string.push(c); | |
| j = i + 1; | |
| } | |
| } | |
| string.push(template.substring(j, i)); | |
| return string.join(""); | |
| } | |
| format.parse = function(string) { | |
| var d = {y: 1900, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0, Z: null}, | |
| i = d3_time_parse(d, template, string, 0); | |
| if (i != string.length) return null; | |
| // The am-pm flag is 0 for AM, and 1 for PM. | |
| if ("p" in d) d.H = d.H % 12 + d.p * 12; | |
| // If a time zone is specified, it is always relative to UTC; | |
| // we need to use d3_date_utc if we aren’t already. | |
| var localZ = d.Z != null && d3_date !== d3_date_utc, | |
| date = new (localZ ? d3_date_utc : d3_date); | |
| // Set year, month, date. | |
| if ("j" in d) date.setFullYear(d.y, 0, d.j); | |
| else if ("w" in d && ("W" in d || "U" in d)) { | |
| date.setFullYear(d.y, 0, 1); | |
| date.setFullYear(d.y, 0, "W" in d | |
| ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 | |
| : d.w + d.U * 7 - (date.getDay() + 6) % 7); | |
| } else date.setFullYear(d.y, d.m, d.d); | |
| // Set hours, minutes, seconds and milliseconds. | |
| date.setHours(d.H + Math.floor(d.Z / 100), d.M + d.Z % 100, d.S, d.L); | |
| return localZ ? date._ : date; | |
| }; | |
| format.toString = function() { | |
| return template; | |
| }; | |
| return format; | |
| } | |
| function d3_time_parse(date, template, string, j) { | |
| var c, | |
| p, | |
| t, | |
| i = 0, | |
| n = template.length, | |
| m = string.length; | |
| while (i < n) { | |
| if (j >= m) return -1; | |
| c = template.charCodeAt(i++); | |
| if (c === 37) { | |
| t = template.charAt(i++); | |
| p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; | |
| if (!p || ((j = p(date, string, j)) < 0)) return -1; | |
| } else if (c != string.charCodeAt(j++)) { | |
| return -1; | |
| } | |
| } | |
| return j; | |
| } | |
| d3_time_format.utc = function(template) { | |
| var local = d3_time_format(template); | |
| function format(date) { | |
| try { | |
| d3_date = d3_date_utc; | |
| var utc = new d3_date(); | |
| utc._ = date; | |
| return local(utc); | |
| } finally { | |
| d3_date = Date; | |
| } | |
| } | |
| format.parse = function(string) { | |
| try { | |
| d3_date = d3_date_utc; | |
| var date = local.parse(string); | |
| return date && date._; | |
| } finally { | |
| d3_date = Date; | |
| } | |
| }; | |
| format.toString = local.toString; | |
| return format; | |
| }; | |
| d3_time_format.multi = | |
| d3_time_format.utc.multi = d3_time_formatMulti; | |
| var d3_time_periodLookup = d3.map(), | |
| d3_time_dayRe = d3_time_formatRe(locale_days), | |
| d3_time_dayLookup = d3_time_formatLookup(locale_days), | |
| d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), | |
| d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), | |
| d3_time_monthRe = d3_time_formatRe(locale_months), | |
| d3_time_monthLookup = d3_time_formatLookup(locale_months), | |
| d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), | |
| d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); | |
| locale_periods.forEach(function(p, i) { | |
| d3_time_periodLookup.set(p.toLowerCase(), i); | |
| }); | |
| var d3_time_formats = { | |
| a: function(d) { return locale_shortDays[d.getDay()]; }, | |
| A: function(d) { return locale_days[d.getDay()]; }, | |
| b: function(d) { return locale_shortMonths[d.getMonth()]; }, | |
| B: function(d) { return locale_months[d.getMonth()]; }, | |
| c: d3_time_format(locale_dateTime), | |
| d: function(d, p) { return d3_time_formatPad(d.getDate(), p, 2); }, | |
| e: function(d, p) { return d3_time_formatPad(d.getDate(), p, 2); }, | |
| H: function(d, p) { return d3_time_formatPad(d.getHours(), p, 2); }, | |
| I: function(d, p) { return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); }, | |
| j: function(d, p) { return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); }, | |
| L: function(d, p) { return d3_time_formatPad(d.getMilliseconds(), p, 3); }, | |
| m: function(d, p) { return d3_time_formatPad(d.getMonth() + 1, p, 2); }, | |
| M: function(d, p) { return d3_time_formatPad(d.getMinutes(), p, 2); }, | |
| p: function(d) { return locale_periods[+(d.getHours() >= 12)]; }, | |
| S: function(d, p) { return d3_time_formatPad(d.getSeconds(), p, 2); }, | |
| U: function(d, p) { return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); }, | |
| w: function(d) { return d.getDay(); }, | |
| W: function(d, p) { return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); }, | |
| x: d3_time_format(locale_date), | |
| X: d3_time_format(locale_time), | |
| y: function(d, p) { return d3_time_formatPad(d.getFullYear() % 100, p, 2); }, | |
| Y: function(d, p) { return d3_time_formatPad(d.getFullYear() % 10000, p, 4); }, | |
| Z: d3_time_zone, | |
| "%": function() { return "%"; } | |
| }; | |
| var d3_time_parsers = { | |
| a: d3_time_parseWeekdayAbbrev, | |
| A: d3_time_parseWeekday, | |
| b: d3_time_parseMonthAbbrev, | |
| B: d3_time_parseMonth, | |
| c: d3_time_parseLocaleFull, | |
| d: d3_time_parseDay, | |
| e: d3_time_parseDay, | |
| H: d3_time_parseHour24, | |
| I: d3_time_parseHour24, | |
| j: d3_time_parseDayOfYear, | |
| L: d3_time_parseMilliseconds, | |
| m: d3_time_parseMonthNumber, | |
| M: d3_time_parseMinutes, | |
| p: d3_time_parseAmPm, | |
| S: d3_time_parseSeconds, | |
| U: d3_time_parseWeekNumberSunday, | |
| w: d3_time_parseWeekdayNumber, | |
| W: d3_time_parseWeekNumberMonday, | |
| x: d3_time_parseLocaleDate, | |
| X: d3_time_parseLocaleTime, | |
| y: d3_time_parseYear, | |
| Y: d3_time_parseFullYear, | |
| Z: d3_time_parseZone, | |
| "%": d3_time_parseLiteralPercent | |
| }; | |
| function d3_time_parseWeekdayAbbrev(date, string, i) { | |
| d3_time_dayAbbrevRe.lastIndex = 0; | |
| var n = d3_time_dayAbbrevRe.exec(string.substring(i)); | |
| return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
| } | |
| function d3_time_parseWeekday(date, string, i) { | |
| d3_time_dayRe.lastIndex = 0; | |
| var n = d3_time_dayRe.exec(string.substring(i)); | |
| return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
| } | |
| function d3_time_parseMonthAbbrev(date, string, i) { | |
| d3_time_monthAbbrevRe.lastIndex = 0; | |
| var n = d3_time_monthAbbrevRe.exec(string.substring(i)); | |
| return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
| } | |
| function d3_time_parseMonth(date, string, i) { | |
| d3_time_monthRe.lastIndex = 0; | |
| var n = d3_time_monthRe.exec(string.substring(i)); | |
| return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
| } | |
| function d3_time_parseLocaleFull(date, string, i) { | |
| return d3_time_parse(date, d3_time_formats.c.toString(), string, i); | |
| } | |
| function d3_time_parseLocaleDate(date, string, i) { | |
| return d3_time_parse(date, d3_time_formats.x.toString(), string, i); | |
| } | |
| function d3_time_parseLocaleTime(date, string, i) { | |
| return d3_time_parse(date, d3_time_formats.X.toString(), string, i); | |
| } | |
| function d3_time_parseAmPm(date, string, i) { | |
| var n = d3_time_periodLookup.get(string.substring(i, i += 2).toLowerCase()); | |
| return n == null ? -1 : (date.p = n, i); | |
| } | |
| return d3_time_format; | |
| } | |
| var d3_time_formatPads = {"-": "", "_": " ", "0": "0"}, | |
| d3_time_numberRe = /^\s*\d+/, // note: ignores next directive | |
| d3_time_percentRe = /^%/; | |
| function d3_time_formatPad(value, fill, width) { | |
| var sign = value < 0 ? "-" : "", | |
| string = (sign ? -value : value) + "", | |
| length = string.length; | |
| return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); | |
| } | |
| function d3_time_formatRe(names) { | |
| return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); | |
| } | |
| function d3_time_formatLookup(names) { | |
| var map = new d3_Map, i = -1, n = names.length; | |
| while (++i < n) map.set(names[i].toLowerCase(), i); | |
| return map; | |
| } | |
| function d3_time_parseWeekdayNumber(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 1)); | |
| return n ? (date.w = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseWeekNumberSunday(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i)); | |
| return n ? (date.U = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseWeekNumberMonday(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i)); | |
| return n ? (date.W = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseFullYear(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 4)); | |
| return n ? (date.y = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseYear(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
| return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; | |
| } | |
| function d3_time_parseZone(date, string, i) { | |
| return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) | |
| ? (date.Z = +string, i + 5) | |
| : -1; | |
| } | |
| function d3_time_expandYear(d) { | |
| return d + (d > 68 ? 1900 : 2000); | |
| } | |
| function d3_time_parseMonthNumber(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
| return n ? (date.m = n[0] - 1, i + n[0].length) : -1; | |
| } | |
| function d3_time_parseDay(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
| return n ? (date.d = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseDayOfYear(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 3)); | |
| return n ? (date.j = +n[0], i + n[0].length) : -1; | |
| } | |
| // Note: we don't validate that the hour is in the range [0,23] or [1,12]. | |
| function d3_time_parseHour24(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
| return n ? (date.H = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseMinutes(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
| return n ? (date.M = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseSeconds(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 2)); | |
| return n ? (date.S = +n[0], i + n[0].length) : -1; | |
| } | |
| function d3_time_parseMilliseconds(date, string, i) { | |
| d3_time_numberRe.lastIndex = 0; | |
| var n = d3_time_numberRe.exec(string.substring(i, i + 3)); | |
| return n ? (date.L = +n[0], i + n[0].length) : -1; | |
| } | |
| // TODO table of time zone offset names? | |
| function d3_time_zone(d) { | |
| var z = d.getTimezoneOffset(), | |
| zs = z > 0 ? "-" : "+", | |
| zh = ~~(abs(z) / 60), | |
| zm = abs(z) % 60; | |
| return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); | |
| } | |
| function d3_time_parseLiteralPercent(date, string, i) { | |
| d3_time_percentRe.lastIndex = 0; | |
| var n = d3_time_percentRe.exec(string.substring(i, i + 1)); | |
| return n ? i + n[0].length : -1; | |
| } | |
| function d3_time_formatMulti(formats) { | |
| var n = formats.length, i = -1; | |
| while (++i < n) formats[i][0] = this(formats[i][0]); | |
| return function(date) { | |
| var i = 0, f = formats[i]; | |
| while (!f[1](date)) f = formats[++i]; | |
| return f[0](date); | |
| }; | |
| } |