UNPKG

3.15 kBJavaScriptView Raw
1import dates from './dates';
2// assumes both are supported or none
3let supportStyles = false;
4new Intl.DateTimeFormat(undefined, {
5 // @ts-ignore
6 get dateStyle() {
7 supportStyles = true;
8 }
9
10});
11const dateShort = {
12 day: 'numeric',
13 month: 'numeric',
14 year: 'numeric'
15};
16const timeShort = {
17 hour: 'numeric',
18 minute: 'numeric'
19};
20
21const getFormatter = (culture, options) => Intl.DateTimeFormat(culture, options).format;
22/**
23 * A `react-widgets` Localizer using native `Intl` APIs.
24 *
25 */
26
27
28class IntlDateLocalizer {
29 constructor({
30 culture = undefined,
31 firstOfWeek = 0
32 } = {}) {
33 this.culture = culture;
34
35 this.firstOfWeek = () => firstOfWeek;
36
37 function normalizeFormat(date, format) {
38 return typeof format === 'function' ? format(date, culture) : date.toLocaleString(culture, format);
39 }
40
41 const formats = {
42 date: getFormatter(culture, supportStyles ? {
43 dateStyle: 'short'
44 } : dateShort),
45 time: getFormatter(culture, supportStyles ? {
46 timeStyle: 'short'
47 } : timeShort),
48 datetime: getFormatter(culture, supportStyles ? {
49 dateStyle: 'short',
50 timeStyle: 'short'
51 } : Object.assign({}, dateShort, timeShort)),
52 header: getFormatter(culture, {
53 month: 'short',
54 year: 'numeric'
55 }),
56 weekday: getFormatter(culture, {
57 weekday: 'narrow'
58 }),
59 dayOfMonth: getFormatter(culture, {
60 day: '2-digit'
61 }),
62 month: getFormatter(culture, {
63 month: 'short'
64 }),
65 year: getFormatter(culture, {
66 year: 'numeric'
67 }),
68 decade: date => `${this.year(date)} - ${this.year(dates.endOf(date, 'decade'))}`,
69 century: date => `${this.year(date)} - ${this.year(dates.endOf(date, 'century'))}`
70 };
71 Object.keys(formats).forEach(key => {
72 this[key] = (date, format) => format ? normalizeFormat(date, format) : formats[key](date);
73 });
74 }
75
76 toFormattedParts(date, format = {
77 dateStyle: 'short',
78 timeStyle: 'short'
79 }) {
80 return Intl.DateTimeFormat(this.culture, format).formatToParts(date).filter(p => p.type !== 'timeZoneName');
81 }
82
83 parse(value) {
84 return new Date(value);
85 }
86
87}
88
89/**
90 * A number localization strategy based on `Intl.NumberFormat`.
91 */
92class IntlNumberLocalizer {
93 constructor({
94 culture = undefined
95 } = {}) {
96 var _$toLocaleString$m;
97
98 this.culture = culture;
99 const decimal = 'formatToParts' in Intl.NumberFormat(culture) ? Intl.NumberFormat(culture).formatToParts(1.1)[1].value : ((_$toLocaleString$m = 1.1.toLocaleString(culture).match(/[^\d]/)) == null ? void 0 : _$toLocaleString$m[0]) || '.';
100 const formatter = Intl.NumberFormat(culture).format;
101
102 this.decimalCharacter = () => decimal;
103
104 this.format = (num, format) => {
105 if (format) {
106 return typeof format === 'function' ? format(num, culture) : num.toLocaleString(culture, format);
107 }
108
109 return formatter(num);
110 };
111 }
112
113 parse(value) {
114 return parseFloat(value.replace(this.decimalCharacter(), '.'));
115 }
116
117}
118
119export { IntlDateLocalizer as DateLocalizer, IntlNumberLocalizer as NumberLocalizer };
\No newline at end of file