import “../arrays/map”; import “../format/requote”; import “day”; import “format-localized”; import “time”; import “week”;

d3.time.format = function(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},
      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;

  var date = new d3_time;
  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);
  date.setHours(d.H, d.M, d.S, d.L);
  return date;
};

format.toString = function() {
  return template;
};

return format;

};

function d3_time_parse(date, template, string, j) {

var c,
    p,
    i = 0,
    n = template.length,
    m = string.length;
while (i < n) {
  if (j >= m) return -1;
  c = template.charCodeAt(i++);
  if (c === 37) {
    p = d3_time_parsers[template.charAt(i++)];
    if (!p || ((j = p(date, string, j)) < 0)) return -1;
  } else if (c != string.charCodeAt(j++)) {
    return -1;
  }
}
return j;

}

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_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);

}

var d3_time_dayRe = d3_time_formatRe(d3_time_days),

d3_time_dayLookup = d3_time_formatLookup(d3_time_days),
d3_time_dayAbbrevRe = d3_time_formatRe(d3_time_dayAbbreviations),
d3_time_dayAbbrevLookup = d3_time_formatLookup(d3_time_dayAbbreviations),
d3_time_monthRe = d3_time_formatRe(d3_time_months),
d3_time_monthLookup = d3_time_formatLookup(d3_time_months),
d3_time_monthAbbrevRe = d3_time_formatRe(d3_time_monthAbbreviations),
d3_time_monthAbbrevLookup = d3_time_formatLookup(d3_time_monthAbbreviations),
d3_time_percentRe = /^%/;

var d3_time_formatPads = {

"-": "",
"_": " ",
"0": "0"

};

var d3_time_formats = {

a: function(d) { return d3_time_dayAbbreviations[d.getDay()]; },
A: function(d) { return d3_time_days[d.getDay()]; },
b: function(d) { return d3_time_monthAbbreviations[d.getMonth()]; },
B: function(d) { return d3_time_months[d.getMonth()]; },
c: d3.time.format(d3_time_formatDateTime),
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 d.getHours() >= 12 ? "PM" : "AM"; },
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(d3_time_formatDate),
X: d3.time.format(d3_time_formatTime),
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: function(d, s, i) { /*TODO time zone */ return i; },
"%": 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_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_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_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_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;

}

// Note: we don't look at the next directive. var d3_time_numberRe = /^s*d+/;

function d3_time_parseAmPm(date, string, i) {

var n = d3_time_amPmLookup.get(string.substring(i, i += 2).toLowerCase());
return n == null ? -1 : (date.p = n, i);

}

var d3_time_amPmLookup = d3.map({

am: 0,
pm: 1

});

// TODO table of time zone offset names? function d3_time_zone(d) {

var z = d.getTimezoneOffset(),
    zs = z > 0 ? "-" : "+",
    zh = ~~(Math.abs(z) / 60),
    zm = Math.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;

}