UNPKG

3.25 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, // @ts-ignore
43 supportStyles ? {
44 dateStyle: 'short'
45 } : dateShort),
46 time: getFormatter(culture, // @ts-ignore
47 supportStyles ? {
48 timeStyle: 'short'
49 } : timeShort),
50 datetime: getFormatter(culture, // @ts-ignore
51 supportStyles ? {
52 dateStyle: 'short',
53 timeStyle: 'short'
54 } : Object.assign({}, dateShort, timeShort)),
55 header: getFormatter(culture, {
56 month: 'short',
57 year: 'numeric'
58 }),
59 weekday: getFormatter(culture, {
60 weekday: 'narrow'
61 }),
62 dayOfMonth: getFormatter(culture, {
63 day: '2-digit'
64 }),
65 month: getFormatter(culture, {
66 month: 'short'
67 }),
68 year: getFormatter(culture, {
69 year: 'numeric'
70 }),
71 decade: date => `${this.year(date)} - ${this.year(dates.endOf(date, 'decade'))}`,
72 century: date => `${this.year(date)} - ${this.year(dates.endOf(date, 'century'))}`
73 };
74 Object.keys(formats).forEach(key => {
75 this[key] = (date, format) => format ? normalizeFormat(date, format) : formats[key](date);
76 });
77 }
78
79 toFormattedParts(date, format = {
80 dateStyle: 'short',
81 timeStyle: 'short'
82 }) {
83 return Intl.DateTimeFormat(this.culture, format).formatToParts(date).filter(p => p.type !== 'timeZoneName');
84 }
85
86 parse(value) {
87 const date = new Date(value);
88 return isNaN(+date) ? null : date;
89 }
90
91}
92
93/**
94 * A number localization strategy based on `Intl.NumberFormat`.
95 */
96class IntlNumberLocalizer {
97 constructor({
98 culture = undefined
99 } = {}) {
100 var _$toLocaleString$m;
101
102 this.culture = culture;
103 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]) || '.';
104 const formatter = Intl.NumberFormat(culture).format;
105
106 this.decimalCharacter = () => decimal;
107
108 this.format = (num, format) => {
109 if (format) {
110 return typeof format === 'function' ? format(num, culture) : num.toLocaleString(culture, format);
111 }
112
113 return formatter(num);
114 };
115 }
116
117 parse(value) {
118 return parseFloat(value.replace(this.decimalCharacter(), '.'));
119 }
120
121}
122
123export { IntlDateLocalizer as DateLocalizer, IntlNumberLocalizer as NumberLocalizer };
\No newline at end of file