UNPKG

17.1 kBJavaScriptView Raw
1import {
2 timeDay,
3 timeSunday,
4 timeMonday,
5 timeThursday,
6 timeYear,
7 utcDay,
8 utcSunday,
9 utcMonday,
10 utcThursday,
11 utcYear
12} from "d3-time";
13
14function localDate(d) {
15 if (0 <= d.y && d.y < 100) {
16 var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
17 date.setFullYear(d.y);
18 return date;
19 }
20 return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
21}
22
23function utcDate(d) {
24 if (0 <= d.y && d.y < 100) {
25 var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
26 date.setUTCFullYear(d.y);
27 return date;
28 }
29 return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
30}
31
32function newYear(y) {
33 return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
34}
35
36export default function formatLocale(locale) {
37 var locale_dateTime = locale.dateTime,
38 locale_date = locale.date,
39 locale_time = locale.time,
40 locale_periods = locale.periods,
41 locale_weekdays = locale.days,
42 locale_shortWeekdays = locale.shortDays,
43 locale_months = locale.months,
44 locale_shortMonths = locale.shortMonths;
45
46 var periodRe = formatRe(locale_periods),
47 periodLookup = formatLookup(locale_periods),
48 weekdayRe = formatRe(locale_weekdays),
49 weekdayLookup = formatLookup(locale_weekdays),
50 shortWeekdayRe = formatRe(locale_shortWeekdays),
51 shortWeekdayLookup = formatLookup(locale_shortWeekdays),
52 monthRe = formatRe(locale_months),
53 monthLookup = formatLookup(locale_months),
54 shortMonthRe = formatRe(locale_shortMonths),
55 shortMonthLookup = formatLookup(locale_shortMonths);
56
57 var formats = {
58 "a": formatShortWeekday,
59 "A": formatWeekday,
60 "b": formatShortMonth,
61 "B": formatMonth,
62 "c": null,
63 "d": formatDayOfMonth,
64 "e": formatDayOfMonth,
65 "f": formatMicroseconds,
66 "H": formatHour24,
67 "I": formatHour12,
68 "j": formatDayOfYear,
69 "L": formatMilliseconds,
70 "m": formatMonthNumber,
71 "M": formatMinutes,
72 "p": formatPeriod,
73 "Q": formatUnixTimestamp,
74 "s": formatUnixTimestampSeconds,
75 "S": formatSeconds,
76 "u": formatWeekdayNumberMonday,
77 "U": formatWeekNumberSunday,
78 "V": formatWeekNumberISO,
79 "w": formatWeekdayNumberSunday,
80 "W": formatWeekNumberMonday,
81 "x": null,
82 "X": null,
83 "y": formatYear,
84 "Y": formatFullYear,
85 "Z": formatZone,
86 "%": formatLiteralPercent
87 };
88
89 var utcFormats = {
90 "a": formatUTCShortWeekday,
91 "A": formatUTCWeekday,
92 "b": formatUTCShortMonth,
93 "B": formatUTCMonth,
94 "c": null,
95 "d": formatUTCDayOfMonth,
96 "e": formatUTCDayOfMonth,
97 "f": formatUTCMicroseconds,
98 "H": formatUTCHour24,
99 "I": formatUTCHour12,
100 "j": formatUTCDayOfYear,
101 "L": formatUTCMilliseconds,
102 "m": formatUTCMonthNumber,
103 "M": formatUTCMinutes,
104 "p": formatUTCPeriod,
105 "Q": formatUnixTimestamp,
106 "s": formatUnixTimestampSeconds,
107 "S": formatUTCSeconds,
108 "u": formatUTCWeekdayNumberMonday,
109 "U": formatUTCWeekNumberSunday,
110 "V": formatUTCWeekNumberISO,
111 "w": formatUTCWeekdayNumberSunday,
112 "W": formatUTCWeekNumberMonday,
113 "x": null,
114 "X": null,
115 "y": formatUTCYear,
116 "Y": formatUTCFullYear,
117 "Z": formatUTCZone,
118 "%": formatLiteralPercent
119 };
120
121 var parses = {
122 "a": parseShortWeekday,
123 "A": parseWeekday,
124 "b": parseShortMonth,
125 "B": parseMonth,
126 "c": parseLocaleDateTime,
127 "d": parseDayOfMonth,
128 "e": parseDayOfMonth,
129 "f": parseMicroseconds,
130 "H": parseHour24,
131 "I": parseHour24,
132 "j": parseDayOfYear,
133 "L": parseMilliseconds,
134 "m": parseMonthNumber,
135 "M": parseMinutes,
136 "p": parsePeriod,
137 "Q": parseUnixTimestamp,
138 "s": parseUnixTimestampSeconds,
139 "S": parseSeconds,
140 "u": parseWeekdayNumberMonday,
141 "U": parseWeekNumberSunday,
142 "V": parseWeekNumberISO,
143 "w": parseWeekdayNumberSunday,
144 "W": parseWeekNumberMonday,
145 "x": parseLocaleDate,
146 "X": parseLocaleTime,
147 "y": parseYear,
148 "Y": parseFullYear,
149 "Z": parseZone,
150 "%": parseLiteralPercent
151 };
152
153 // These recursive directive definitions must be deferred.
154 formats.x = newFormat(locale_date, formats);
155 formats.X = newFormat(locale_time, formats);
156 formats.c = newFormat(locale_dateTime, formats);
157 utcFormats.x = newFormat(locale_date, utcFormats);
158 utcFormats.X = newFormat(locale_time, utcFormats);
159 utcFormats.c = newFormat(locale_dateTime, utcFormats);
160
161 function newFormat(specifier, formats) {
162 return function(date) {
163 var string = [],
164 i = -1,
165 j = 0,
166 n = specifier.length,
167 c,
168 pad,
169 format;
170
171 if (!(date instanceof Date)) date = new Date(+date);
172
173 while (++i < n) {
174 if (specifier.charCodeAt(i) === 37) {
175 string.push(specifier.slice(j, i));
176 if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
177 else pad = c === "e" ? " " : "0";
178 if (format = formats[c]) c = format(date, pad);
179 string.push(c);
180 j = i + 1;
181 }
182 }
183
184 string.push(specifier.slice(j, i));
185 return string.join("");
186 };
187 }
188
189 function newParse(specifier, newDate) {
190 return function(string) {
191 var d = newYear(1900),
192 i = parseSpecifier(d, specifier, string += "", 0),
193 week, day;
194 if (i != string.length) return null;
195
196 // If a UNIX timestamp is specified, return it.
197 if ("Q" in d) return new Date(d.Q);
198
199 // The am-pm flag is 0 for AM, and 1 for PM.
200 if ("p" in d) d.H = d.H % 12 + d.p * 12;
201
202 // Convert day-of-week and week-of-year to day-of-year.
203 if ("V" in d) {
204 if (d.V < 1 || d.V > 53) return null;
205 if (!("w" in d)) d.w = 1;
206 if ("Z" in d) {
207 week = utcDate(newYear(d.y)), day = week.getUTCDay();
208 week = day > 4 || day === 0 ? utcMonday.ceil(week) : utcMonday(week);
209 week = utcDay.offset(week, (d.V - 1) * 7);
210 d.y = week.getUTCFullYear();
211 d.m = week.getUTCMonth();
212 d.d = week.getUTCDate() + (d.w + 6) % 7;
213 } else {
214 week = newDate(newYear(d.y)), day = week.getDay();
215 week = day > 4 || day === 0 ? timeMonday.ceil(week) : timeMonday(week);
216 week = timeDay.offset(week, (d.V - 1) * 7);
217 d.y = week.getFullYear();
218 d.m = week.getMonth();
219 d.d = week.getDate() + (d.w + 6) % 7;
220 }
221 } else if ("W" in d || "U" in d) {
222 if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0;
223 day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
224 d.m = 0;
225 d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;
226 }
227
228 // If a time zone is specified, all fields are interpreted as UTC and then
229 // offset according to the specified time zone.
230 if ("Z" in d) {
231 d.H += d.Z / 100 | 0;
232 d.M += d.Z % 100;
233 return utcDate(d);
234 }
235
236 // Otherwise, all fields are in local time.
237 return newDate(d);
238 };
239 }
240
241 function parseSpecifier(d, specifier, string, j) {
242 var i = 0,
243 n = specifier.length,
244 m = string.length,
245 c,
246 parse;
247
248 while (i < n) {
249 if (j >= m) return -1;
250 c = specifier.charCodeAt(i++);
251 if (c === 37) {
252 c = specifier.charAt(i++);
253 parse = parses[c in pads ? specifier.charAt(i++) : c];
254 if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
255 } else if (c != string.charCodeAt(j++)) {
256 return -1;
257 }
258 }
259
260 return j;
261 }
262
263 function parsePeriod(d, string, i) {
264 var n = periodRe.exec(string.slice(i));
265 return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
266 }
267
268 function parseShortWeekday(d, string, i) {
269 var n = shortWeekdayRe.exec(string.slice(i));
270 return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
271 }
272
273 function parseWeekday(d, string, i) {
274 var n = weekdayRe.exec(string.slice(i));
275 return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
276 }
277
278 function parseShortMonth(d, string, i) {
279 var n = shortMonthRe.exec(string.slice(i));
280 return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
281 }
282
283 function parseMonth(d, string, i) {
284 var n = monthRe.exec(string.slice(i));
285 return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
286 }
287
288 function parseLocaleDateTime(d, string, i) {
289 return parseSpecifier(d, locale_dateTime, string, i);
290 }
291
292 function parseLocaleDate(d, string, i) {
293 return parseSpecifier(d, locale_date, string, i);
294 }
295
296 function parseLocaleTime(d, string, i) {
297 return parseSpecifier(d, locale_time, string, i);
298 }
299
300 function formatShortWeekday(d) {
301 return locale_shortWeekdays[d.getDay()];
302 }
303
304 function formatWeekday(d) {
305 return locale_weekdays[d.getDay()];
306 }
307
308 function formatShortMonth(d) {
309 return locale_shortMonths[d.getMonth()];
310 }
311
312 function formatMonth(d) {
313 return locale_months[d.getMonth()];
314 }
315
316 function formatPeriod(d) {
317 return locale_periods[+(d.getHours() >= 12)];
318 }
319
320 function formatUTCShortWeekday(d) {
321 return locale_shortWeekdays[d.getUTCDay()];
322 }
323
324 function formatUTCWeekday(d) {
325 return locale_weekdays[d.getUTCDay()];
326 }
327
328 function formatUTCShortMonth(d) {
329 return locale_shortMonths[d.getUTCMonth()];
330 }
331
332 function formatUTCMonth(d) {
333 return locale_months[d.getUTCMonth()];
334 }
335
336 function formatUTCPeriod(d) {
337 return locale_periods[+(d.getUTCHours() >= 12)];
338 }
339
340 return {
341 format: function(specifier) {
342 var f = newFormat(specifier += "", formats);
343 f.toString = function() { return specifier; };
344 return f;
345 },
346 parse: function(specifier) {
347 var p = newParse(specifier += "", localDate);
348 p.toString = function() { return specifier; };
349 return p;
350 },
351 utcFormat: function(specifier) {
352 var f = newFormat(specifier += "", utcFormats);
353 f.toString = function() { return specifier; };
354 return f;
355 },
356 utcParse: function(specifier) {
357 var p = newParse(specifier, utcDate);
358 p.toString = function() { return specifier; };
359 return p;
360 }
361 };
362}
363
364var pads = {"-": "", "_": " ", "0": "0"},
365 numberRe = /^\s*\d+/, // note: ignores next directive
366 percentRe = /^%/,
367 requoteRe = /[\\^$*+?|[\]().{}]/g;
368
369function pad(value, fill, width) {
370 var sign = value < 0 ? "-" : "",
371 string = (sign ? -value : value) + "",
372 length = string.length;
373 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
374}
375
376function requote(s) {
377 return s.replace(requoteRe, "\\$&");
378}
379
380function formatRe(names) {
381 return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
382}
383
384function formatLookup(names) {
385 var map = {}, i = -1, n = names.length;
386 while (++i < n) map[names[i].toLowerCase()] = i;
387 return map;
388}
389
390function parseWeekdayNumberSunday(d, string, i) {
391 var n = numberRe.exec(string.slice(i, i + 1));
392 return n ? (d.w = +n[0], i + n[0].length) : -1;
393}
394
395function parseWeekdayNumberMonday(d, string, i) {
396 var n = numberRe.exec(string.slice(i, i + 1));
397 return n ? (d.u = +n[0], i + n[0].length) : -1;
398}
399
400function parseWeekNumberSunday(d, string, i) {
401 var n = numberRe.exec(string.slice(i, i + 2));
402 return n ? (d.U = +n[0], i + n[0].length) : -1;
403}
404
405function parseWeekNumberISO(d, string, i) {
406 var n = numberRe.exec(string.slice(i, i + 2));
407 return n ? (d.V = +n[0], i + n[0].length) : -1;
408}
409
410function parseWeekNumberMonday(d, string, i) {
411 var n = numberRe.exec(string.slice(i, i + 2));
412 return n ? (d.W = +n[0], i + n[0].length) : -1;
413}
414
415function parseFullYear(d, string, i) {
416 var n = numberRe.exec(string.slice(i, i + 4));
417 return n ? (d.y = +n[0], i + n[0].length) : -1;
418}
419
420function parseYear(d, string, i) {
421 var n = numberRe.exec(string.slice(i, i + 2));
422 return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
423}
424
425function parseZone(d, string, i) {
426 var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6));
427 return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
428}
429
430function parseMonthNumber(d, string, i) {
431 var n = numberRe.exec(string.slice(i, i + 2));
432 return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
433}
434
435function parseDayOfMonth(d, string, i) {
436 var n = numberRe.exec(string.slice(i, i + 2));
437 return n ? (d.d = +n[0], i + n[0].length) : -1;
438}
439
440function parseDayOfYear(d, string, i) {
441 var n = numberRe.exec(string.slice(i, i + 3));
442 return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
443}
444
445function parseHour24(d, string, i) {
446 var n = numberRe.exec(string.slice(i, i + 2));
447 return n ? (d.H = +n[0], i + n[0].length) : -1;
448}
449
450function parseMinutes(d, string, i) {
451 var n = numberRe.exec(string.slice(i, i + 2));
452 return n ? (d.M = +n[0], i + n[0].length) : -1;
453}
454
455function parseSeconds(d, string, i) {
456 var n = numberRe.exec(string.slice(i, i + 2));
457 return n ? (d.S = +n[0], i + n[0].length) : -1;
458}
459
460function parseMilliseconds(d, string, i) {
461 var n = numberRe.exec(string.slice(i, i + 3));
462 return n ? (d.L = +n[0], i + n[0].length) : -1;
463}
464
465function parseMicroseconds(d, string, i) {
466 var n = numberRe.exec(string.slice(i, i + 6));
467 return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1;
468}
469
470function parseLiteralPercent(d, string, i) {
471 var n = percentRe.exec(string.slice(i, i + 1));
472 return n ? i + n[0].length : -1;
473}
474
475function parseUnixTimestamp(d, string, i) {
476 var n = numberRe.exec(string.slice(i));
477 return n ? (d.Q = +n[0], i + n[0].length) : -1;
478}
479
480function parseUnixTimestampSeconds(d, string, i) {
481 var n = numberRe.exec(string.slice(i));
482 return n ? (d.Q = (+n[0]) * 1000, i + n[0].length) : -1;
483}
484
485function formatDayOfMonth(d, p) {
486 return pad(d.getDate(), p, 2);
487}
488
489function formatHour24(d, p) {
490 return pad(d.getHours(), p, 2);
491}
492
493function formatHour12(d, p) {
494 return pad(d.getHours() % 12 || 12, p, 2);
495}
496
497function formatDayOfYear(d, p) {
498 return pad(1 + timeDay.count(timeYear(d), d), p, 3);
499}
500
501function formatMilliseconds(d, p) {
502 return pad(d.getMilliseconds(), p, 3);
503}
504
505function formatMicroseconds(d, p) {
506 return formatMilliseconds(d, p) + "000";
507}
508
509function formatMonthNumber(d, p) {
510 return pad(d.getMonth() + 1, p, 2);
511}
512
513function formatMinutes(d, p) {
514 return pad(d.getMinutes(), p, 2);
515}
516
517function formatSeconds(d, p) {
518 return pad(d.getSeconds(), p, 2);
519}
520
521function formatWeekdayNumberMonday(d) {
522 var day = d.getDay();
523 return day === 0 ? 7 : day;
524}
525
526function formatWeekNumberSunday(d, p) {
527 return pad(timeSunday.count(timeYear(d), d), p, 2);
528}
529
530function formatWeekNumberISO(d, p) {
531 var day = d.getDay();
532 d = (day >= 4 || day === 0) ? timeThursday(d) : timeThursday.ceil(d);
533 return pad(timeThursday.count(timeYear(d), d) + (timeYear(d).getDay() === 4), p, 2);
534}
535
536function formatWeekdayNumberSunday(d) {
537 return d.getDay();
538}
539
540function formatWeekNumberMonday(d, p) {
541 return pad(timeMonday.count(timeYear(d), d), p, 2);
542}
543
544function formatYear(d, p) {
545 return pad(d.getFullYear() % 100, p, 2);
546}
547
548function formatFullYear(d, p) {
549 return pad(d.getFullYear() % 10000, p, 4);
550}
551
552function formatZone(d) {
553 var z = d.getTimezoneOffset();
554 return (z > 0 ? "-" : (z *= -1, "+"))
555 + pad(z / 60 | 0, "0", 2)
556 + pad(z % 60, "0", 2);
557}
558
559function formatUTCDayOfMonth(d, p) {
560 return pad(d.getUTCDate(), p, 2);
561}
562
563function formatUTCHour24(d, p) {
564 return pad(d.getUTCHours(), p, 2);
565}
566
567function formatUTCHour12(d, p) {
568 return pad(d.getUTCHours() % 12 || 12, p, 2);
569}
570
571function formatUTCDayOfYear(d, p) {
572 return pad(1 + utcDay.count(utcYear(d), d), p, 3);
573}
574
575function formatUTCMilliseconds(d, p) {
576 return pad(d.getUTCMilliseconds(), p, 3);
577}
578
579function formatUTCMicroseconds(d, p) {
580 return formatUTCMilliseconds(d, p) + "000";
581}
582
583function formatUTCMonthNumber(d, p) {
584 return pad(d.getUTCMonth() + 1, p, 2);
585}
586
587function formatUTCMinutes(d, p) {
588 return pad(d.getUTCMinutes(), p, 2);
589}
590
591function formatUTCSeconds(d, p) {
592 return pad(d.getUTCSeconds(), p, 2);
593}
594
595function formatUTCWeekdayNumberMonday(d) {
596 var dow = d.getUTCDay();
597 return dow === 0 ? 7 : dow;
598}
599
600function formatUTCWeekNumberSunday(d, p) {
601 return pad(utcSunday.count(utcYear(d), d), p, 2);
602}
603
604function formatUTCWeekNumberISO(d, p) {
605 var day = d.getUTCDay();
606 d = (day >= 4 || day === 0) ? utcThursday(d) : utcThursday.ceil(d);
607 return pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2);
608}
609
610function formatUTCWeekdayNumberSunday(d) {
611 return d.getUTCDay();
612}
613
614function formatUTCWeekNumberMonday(d, p) {
615 return pad(utcMonday.count(utcYear(d), d), p, 2);
616}
617
618function formatUTCYear(d, p) {
619 return pad(d.getUTCFullYear() % 100, p, 2);
620}
621
622function formatUTCFullYear(d, p) {
623 return pad(d.getUTCFullYear() % 10000, p, 4);
624}
625
626function formatUTCZone() {
627 return "+0000";
628}
629
630function formatLiteralPercent() {
631 return "%";
632}
633
634function formatUnixTimestamp(d) {
635 return +d;
636}
637
638function formatUnixTimestampSeconds(d) {
639 return Math.floor(+d / 1000);
640}