UNPKG

10.2 kBPlain TextView Raw
1import defaultMoment, { LongDateFormatKey } from "moment";
2import { IUtils, DateIOFormats, Unit } from "@date-io/core/IUtils";
3
4interface Opts {
5 locale?: string;
6 instance?: typeof defaultMoment;
7 formats?: Partial<DateIOFormats>;
8}
9
10type Moment = defaultMoment.Moment;
11const defaultFormats: DateIOFormats = {
12 normalDateWithWeekday: "ddd, MMM D",
13 normalDate: "D MMMM",
14 shortDate: "MMM D",
15 monthAndDate: "MMMM D",
16 dayOfMonth: "D",
17 year: "YYYY",
18 month: "MMMM",
19 monthShort: "MMM",
20 monthAndYear: "MMMM YYYY",
21 weekday: "dddd",
22 weekdayShort: "ddd",
23 minutes: "mm",
24 hours12h: "hh",
25 hours24h: "HH",
26 seconds: "ss",
27 fullTime: "LT",
28 fullTime12h: "hh:mm A",
29 fullTime24h: "HH:mm",
30 fullDate: "ll",
31 fullDateWithWeekday: "dddd, LL",
32 fullDateTime: "lll",
33 fullDateTime12h: "ll hh:mm A",
34 fullDateTime24h: "ll HH:mm",
35 keyboardDate: "L",
36 keyboardDateTime: "L LT",
37 keyboardDateTime12h: "L hh:mm A",
38 keyboardDateTime24h: "L HH:mm",
39};
40
41export default class MomentUtils implements IUtils<defaultMoment.Moment> {
42 public moment: typeof defaultMoment;
43 public lib = "moment";
44 public locale?: string;
45 public formats: DateIOFormats;
46
47 constructor({ locale, formats, instance }: Opts = {}) {
48 this.moment = instance || defaultMoment;
49 this.locale = locale;
50
51 this.formats = Object.assign({}, defaultFormats, formats);
52 }
53
54 public is12HourCycleInCurrentLocale = () => {
55 return /A|a/.test(
56 this.moment.localeData(this.getCurrentLocaleCode()).longDateFormat("LT")
57 );
58 };
59
60 public getFormatHelperText = (format: string) => {
61 // @see https://github.com/moment/moment/blob/develop/src/lib/format/format.js#L6
62 const localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})|./g;
63 return format
64 .match(localFormattingTokens)
65 .map((token) => {
66 const firstCharacter = token[0];
67 if (firstCharacter === "L" || firstCharacter === ";") {
68 return this.moment
69 .localeData(this.getCurrentLocaleCode())
70 .longDateFormat(token as LongDateFormatKey);
71 }
72
73 return token;
74 })
75 .join("")
76 .replace(/a/gi, "(a|p)m")
77 .toLocaleLowerCase();
78 };
79
80 public getCurrentLocaleCode = () => {
81 return this.locale || this.moment.locale();
82 };
83
84 public parseISO = (isoString: string) => {
85 return this.moment(isoString, true);
86 };
87
88 public toISO = (value: Moment) => {
89 return value.toISOString();
90 };
91
92 public parse = (value: string, format: string) => {
93 if (value === "") {
94 return null;
95 }
96
97 if (this.locale) {
98 return this.moment(value, format, this.locale, true);
99 }
100
101 return this.moment(value, format, true);
102 };
103
104 public date = (value?: any) => {
105 if (value === null) {
106 return null;
107 }
108
109 const moment = this.moment(value);
110 moment.locale(this.locale);
111
112 return moment;
113 };
114
115 public toJsDate = (value: Moment) => {
116 return value.toDate();
117 };
118
119 public isValid = (value: any) => {
120 return this.moment(value).isValid();
121 };
122
123 public isNull = (date: Moment) => {
124 return date === null;
125 };
126
127 public getDiff = (date: Moment, comparing: Moment | string, unit?: Unit) => {
128 return date.diff(comparing, unit);
129 };
130
131 public isAfter = (date: Moment, value: Moment) => {
132 return date.isAfter(value);
133 };
134
135 public isBefore = (date: Moment, value: Moment) => {
136 return date.isBefore(value);
137 };
138
139 public isAfterDay = (date: Moment, value: Moment) => {
140 return date.isAfter(value, "day");
141 };
142
143 public isBeforeDay = (date: Moment, value: Moment) => {
144 return date.isBefore(value, "day");
145 };
146
147 public isBeforeYear = (date: Moment, value: Moment) => {
148 return date.isBefore(value, "year");
149 };
150
151 public isAfterYear = (date: Moment, value: Moment) => {
152 return date.isAfter(value, "year");
153 };
154
155 public startOfDay = (date: Moment) => {
156 return date.clone().startOf("day");
157 };
158
159 public endOfDay = (date: Moment) => {
160 return date.clone().endOf("day");
161 };
162
163 public format = (date: Moment, formatKey: keyof DateIOFormats) => {
164 return this.formatByString(date, this.formats[formatKey]);
165 };
166
167 public formatByString = (date: Moment, formatString: string) => {
168 const clonedDate = date.clone();
169 clonedDate.locale(this.locale);
170 return clonedDate.format(formatString);
171 };
172
173 public formatNumber = (numberToFormat: string) => {
174 return numberToFormat;
175 };
176
177 public getHours = (date: Moment) => {
178 return date.get("hours");
179 };
180
181 public addSeconds = (date: Moment, count: number) => {
182 return count < 0
183 ? date.clone().subtract(Math.abs(count), "seconds")
184 : date.clone().add(count, "seconds");
185 };
186
187 public addMinutes = (date: Moment, count: number) => {
188 return count < 0
189 ? date.clone().subtract(Math.abs(count), "minutes")
190 : date.clone().add(count, "minutes");
191 };
192
193 public addHours = (date: Moment, count: number) => {
194 return count < 0
195 ? date.clone().subtract(Math.abs(count), "hours")
196 : date.clone().add(count, "hours");
197 };
198
199 public addDays = (date: Moment, count: number) => {
200 return count < 0
201 ? date.clone().subtract(Math.abs(count), "days")
202 : date.clone().add(count, "days");
203 };
204
205 public addWeeks = (date: Moment, count: number) => {
206 return count < 0
207 ? date.clone().subtract(Math.abs(count), "weeks")
208 : date.clone().add(count, "weeks");
209 };
210
211 public addMonths = (date: Moment, count: number) => {
212 return count < 0
213 ? date.clone().subtract(Math.abs(count), "months")
214 : date.clone().add(count, "months");
215 };
216
217 public addYears = (date: Moment, count: number) => {
218 return count < 0
219 ? date.clone().subtract(Math.abs(count), "years")
220 : date.clone().add(count, "years");
221 };
222
223 public setHours = (date: Moment, count: number) => {
224 return date.clone().hours(count);
225 };
226
227 public getMinutes = (date: Moment) => {
228 return date.get("minutes");
229 };
230
231 public setMinutes = (date: Moment, count: number) => {
232 return date.clone().minutes(count);
233 };
234
235 public getSeconds = (date: Moment) => {
236 return date.get("seconds");
237 };
238
239 public setSeconds = (date: Moment, count: number) => {
240 return date.clone().seconds(count);
241 };
242
243 public getMonth = (date: Moment) => {
244 return date.get("month");
245 };
246
247 public getDaysInMonth = (date: Moment) => {
248 return date.daysInMonth();
249 };
250
251 public isSameDay = (date: Moment, comparing: Moment) => {
252 return date.isSame(comparing, "day");
253 };
254
255 public isSameMonth = (date: Moment, comparing: Moment) => {
256 return date.isSame(comparing, "month");
257 };
258
259 public isSameYear = (date: Moment, comparing: Moment) => {
260 return date.isSame(comparing, "year");
261 };
262
263 public isSameHour = (date: Moment, comparing: Moment) => {
264 return date.isSame(comparing, "hour");
265 };
266
267 public setMonth = (date: Moment, count: number) => {
268 return date.clone().month(count);
269 };
270
271 public getMeridiemText = (ampm: "am" | "pm") => {
272 if (this.is12HourCycleInCurrentLocale()) {
273 // AM/PM translation only possible in those who have 12 hour cycle in locale.
274 return this.moment
275 .localeData(this.getCurrentLocaleCode())
276 .meridiem(ampm === "am" ? 0 : 13, 0, false);
277 }
278
279 return ampm === "am" ? "AM" : "PM"; // fallback for de, ru, ...etc
280 };
281
282 public startOfYear = (date: Moment) => {
283 return date.clone().startOf("year");
284 };
285
286 public endOfYear = (date: Moment) => {
287 return date.clone().endOf("year");
288 };
289
290 public startOfMonth = (date: Moment) => {
291 return date.clone().startOf("month");
292 };
293
294 public endOfMonth = (date: Moment) => {
295 return date.clone().endOf("month");
296 };
297
298 public startOfWeek = (date: Moment) => {
299 return date.clone().startOf("week");
300 };
301
302 public endOfWeek = (date: Moment) => {
303 return date.clone().endOf("week");
304 };
305
306 public getNextMonth = (date: Moment) => {
307 return date.clone().add(1, "month");
308 };
309
310 public getPreviousMonth = (date: Moment) => {
311 return date.clone().subtract(1, "month");
312 };
313
314 public getMonthArray = (date: Moment) => {
315 const firstMonth = date.clone().startOf("year");
316 const monthArray = [firstMonth];
317
318 while (monthArray.length < 12) {
319 const prevMonth = monthArray[monthArray.length - 1];
320 monthArray.push(this.getNextMonth(prevMonth));
321 }
322
323 return monthArray;
324 };
325
326 public getYear = (date: Moment) => {
327 return date.get("year");
328 };
329
330 public setYear = (date: Moment, year: number) => {
331 return date.clone().set("year", year);
332 };
333
334 public getDate = (date: Moment) => {
335 return date.get("date");
336 };
337
338 public setDate = (date: Moment, year: number) => {
339 return date.clone().set("date", year);
340 };
341
342 public mergeDateAndTime = (date: Moment, time: Moment) => {
343 return date.hour(time.hour()).minute(time.minute()).second(time.second());
344 };
345
346 public getWeekdays = () => {
347 return this.moment.weekdaysShort(true);
348 };
349
350 public isEqual = (value: any, comparing: any) => {
351 if (value === null && comparing === null) {
352 return true;
353 }
354
355 return this.moment(value).isSame(comparing);
356 };
357
358 public getWeekArray = (date: Moment) => {
359 const start = date.clone().startOf("month").startOf("week");
360 const end = date.clone().endOf("month").endOf("week");
361
362 let count = 0;
363 let current = start;
364 const nestedWeeks: Moment[][] = [];
365
366 while (current.isBefore(end)) {
367 const weekNumber = Math.floor(count / 7);
368 nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || [];
369 nestedWeeks[weekNumber].push(current);
370
371 current = current.clone().add(1, "day");
372 count += 1;
373 }
374
375 return nestedWeeks;
376 };
377
378 public getYearRange = (start: Moment, end: Moment) => {
379 const startDate = this.moment(start).startOf("year");
380 const endDate = this.moment(end).endOf("year");
381 const years: Moment[] = [];
382
383 let current = startDate;
384 while (current.isBefore(endDate)) {
385 years.push(current);
386 current = current.clone().add(1, "year");
387 }
388
389 return years;
390 };
391
392 public isWithinRange = (date: Moment, [start, end]: [Moment, Moment]) => {
393 return date.isBetween(start, end, null, "[]");
394 };
395}