omniserror
Version:
Abstraction over common javascript date management libraries
354 lines (281 loc) • 8.59 kB
text/typescript
import { DateTime, Settings, Info } from "luxon";
import { IUtils, DateIOFormats } from "@date-io/core/IUtils";
const defaultFormats: DateIOFormats = {
dayOfMonth: "d",
fullDate: "DD",
fullDateTime: "ff",
fullDateTime12h: "DD, hh:mm a",
fullDateTime24h: "DD, T",
fullTime: "t",
fullTime12h: "hh:mm a",
fullTime24h: "HH:mm",
hours12h: "hh",
hours24h: "HH",
keyboardDate: "D",
keyboardDateTime: "D t",
keyboardDateTime12h: "D hh:mm a",
keyboardDateTime24h: "D T",
minutes: "mm",
seconds: "ss",
month: "LLLL",
monthAndDate: "MMMM d",
monthAndYear: "LLLL yyyy",
monthShort: "MMM",
normalDate: "d MMMM",
normalDateWithWeekday: "EEE, MMM d",
shortDate: "MMM d",
year: "yyyy"
};
export default class LuxonUtils implements IUtils<DateTime> {
public locale: string;
public formats: DateIOFormats;
constructor({
locale,
formats
}: { formats?: Partial<DateIOFormats>; locale?: string } = {}) {
this.locale = locale || "en";
this.formats = Object.assign({}, defaultFormats, formats);
}
public date(value?: any) {
if (typeof value === "undefined") {
return DateTime.local();
}
if (value === null) {
return null;
}
if (typeof value === "string") {
return DateTime.fromJSDate(new Date(value));
}
if (value instanceof DateTime) {
return value;
}
return DateTime.fromJSDate(value);
}
public toJsDate(value: DateTime) {
return value.toJSDate();
}
public parse(value: string, formatString: string) {
if (value === "") {
return null;
}
return DateTime.fromFormat(value, formatString);
}
/* istanbul ignore next */
public is12HourCycleInCurrentLocale() {
if (typeof Intl === "undefined" || typeof Intl.DateTimeFormat === "undefined") {
return true; // Luxon defaults to en-US if Intl not found
}
return Boolean(
new Intl.DateTimeFormat(this.locale, { hour: "numeric" })?.resolvedOptions()?.hour12
);
}
public getFormatHelperText(format: string) {
// Unfortunately there is no way for luxon to retrieve readable formats from localized format
return "";
}
/* istanbul ignore next */
public getCurrentLocaleCode() {
return this.locale || Settings.defaultLocale;
}
public addDays(date: DateTime, count: number) {
return count < 0 ? date.minus({ days: Math.abs(count) }) : date.plus({ days: count });
}
public addMonths(date: DateTime, count: number) {
return count < 0
? date.minus({ months: Math.abs(count) })
: date.plus({ months: count });
}
public isValid(value: any) {
if (value instanceof DateTime) {
return value.isValid;
}
if (value === null) {
return false;
}
return this.date(value).isValid;
}
public isEqual(value: any, comparing: any) {
if (value === null && comparing === null) {
return true;
}
// make sure that null will not be passed to this.date
if (value === null || comparing === null) {
return false;
}
return this.date(value).equals(this.date(comparing));
}
public isSameDay(date: DateTime, comparing: DateTime) {
return date.hasSame(comparing, "day");
}
public isSameMonth(date: DateTime, comparing: DateTime) {
return date.hasSame(comparing, "month");
}
public isSameYear(date: DateTime, comparing: DateTime) {
return date.hasSame(comparing, "year");
}
public isSameHour(date: DateTime, comparing: DateTime) {
return date.hasSame(comparing, "hour");
}
public isAfter(value: DateTime, comparing: DateTime) {
return value > comparing;
}
public isBefore(value: DateTime, comparing: DateTime) {
return value < comparing;
}
public isBeforeDay(value: DateTime, comparing: DateTime) {
const diff = value.diff(comparing.startOf("day"), "days").toObject();
return diff.days! < 0;
}
public isAfterDay(value: DateTime, comparing: DateTime) {
const diff = value.diff(comparing.endOf("day"), "days").toObject();
return diff.days! > 0;
}
public isBeforeYear(value: DateTime, comparing: DateTime) {
const diff = value.diff(comparing.startOf("year"), "years").toObject();
return diff.years! < 0;
}
public isAfterYear(value: DateTime, comparing: DateTime) {
const diff = value.diff(comparing.endOf("year"), "years").toObject();
return diff.years! > 0;
}
public getDiff(value: DateTime, comparing: DateTime | string) {
if (typeof comparing === "string") {
comparing = DateTime.fromJSDate(new Date(comparing));
}
return value.diff(comparing).as("millisecond");
}
public startOfDay(value: DateTime) {
return value.startOf("day");
}
public endOfDay(value: DateTime) {
return value.endOf("day");
}
public format(date: DateTime, formatKey: keyof DateIOFormats) {
return this.formatByString(date, this.formats[formatKey]);
}
public formatByString(date: DateTime, format: string) {
return date.setLocale(this.locale).toFormat(format);
}
public formatNumber(numberToFormat: string) {
return numberToFormat;
}
public getHours(value: DateTime) {
return value.get("hour");
}
public setHours(value: DateTime, count: number) {
return value.set({ hour: count });
}
public getMinutes(value: DateTime) {
return value.get("minute");
}
public setMinutes(value: DateTime, count: number) {
return value.set({ minute: count });
}
public getSeconds(value: DateTime) {
return value.get("second");
}
public setSeconds(value: DateTime, count: number) {
return value.set({ second: count });
}
public getMonth(value: DateTime) {
// See https://github.com/moment/luxon/blob/master/docs/moment.md#major-functional-differences
return value.get("month") - 1;
}
public setMonth(value: DateTime, count: number) {
return value.set({ month: count + 1 });
}
public getYear(value: DateTime) {
return value.get("year");
}
public setYear(value: DateTime, year: number) {
return value.set({ year });
}
public mergeDateAndTime(date: DateTime, time: DateTime) {
return date.set({
second: time.second,
hour: time.hour,
minute: time.minute
});
}
public startOfMonth(value: DateTime) {
return value.startOf("month");
}
public endOfMonth(value: DateTime) {
return value.endOf("month");
}
public startOfWeek(value: DateTime) {
return value.startOf("week");
}
public endOfWeek(value: DateTime) {
return value.endOf("week");
}
public getNextMonth(value: DateTime) {
return value.plus({ months: 1 });
}
public getPreviousMonth(value: DateTime) {
return value.minus({ months: 1 });
}
public getMonthArray(date: DateTime) {
const firstMonth = this.date(date).startOf("year");
const monthArray = [firstMonth];
while (monthArray.length < 12) {
const prevMonth = monthArray[monthArray.length - 1];
monthArray.push(this.getNextMonth(prevMonth));
}
return monthArray;
}
public getWeekdays() {
return Info.weekdaysFormat("narrow", { locale: this.locale });
}
public getWeekArray(date: DateTime) {
const { days } = date
.endOf("month")
.endOf("week")
.diff(date.startOf("month").startOf("week"), "days")
.toObject();
const weeks: DateTime[][] = [];
new Array<number>(Math.round(days!))
.fill(0)
.map((_, i) => i)
.map(day =>
date
.startOf("month")
.startOf("week")
.plus({ days: day })
)
.forEach((v, i) => {
if (i === 0 || (i % 7 === 0 && i > 6)) {
weeks.push([v]);
return;
}
weeks[weeks.length - 1].push(v);
});
return weeks;
}
public getYearRange(start: DateTime, end: DateTime) {
const startDate = this.date(start).startOf("year");
const endDate = this.date(end).endOf("year");
let current = startDate;
const years: DateTime[] = [];
while (current < endDate) {
years.push(current);
current = current.plus({ year: 1 });
}
return years;
}
public getMeridiemText(ampm: "am" | "pm") {
return Info.meridiems({ locale: this.locale }).find(
v => v.toLowerCase() === ampm.toLowerCase()
)!;
}
public isNull(date: DateTime | null) {
return date === null;
}
public isWithinRange(date: DateTime, [start, end]: [DateTime, DateTime]) {
return (
date.equals(start) ||
date.equals(end) ||
(this.isAfter(date, start) && this.isBefore(date, end))
);
}
}