73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { moment } from 'obsidian';
|
|
|
|
const momentFn = 'default' in moment ? moment.default : moment;
|
|
|
|
export class DateFormatter {
|
|
private static readonly RFC2822_FORMAT = 'ddd, DD MMM YYYY HH:mm:ss ZZ';
|
|
|
|
toFormat: string;
|
|
locale: string;
|
|
|
|
constructor() {
|
|
this.toFormat = 'YYYY-MM-DD';
|
|
// get locale of this machine (e.g. en, en-gb, de, fr, etc.)
|
|
this.locale = new Intl.DateTimeFormat().resolvedOptions().locale;
|
|
}
|
|
|
|
setFormat(format: string): void {
|
|
this.toFormat = format;
|
|
}
|
|
|
|
getPreview(format?: string): string {
|
|
const today = momentFn();
|
|
|
|
format ??= this.toFormat;
|
|
|
|
return today.locale(this.locale).format(format);
|
|
}
|
|
|
|
/**
|
|
* Tries to format a given date string with the currently set date format.
|
|
* You can set a date format by calling `setFormat()`.
|
|
*
|
|
* @param dateString the date string to be formatted
|
|
* @param dateFormat the current format of `dateString`. When this is `null` and the actual format of the
|
|
* given date string is not `C2822` or `ISO` format, this function will try to guess the format by using the native `Date` module.
|
|
* @param locale the locale of `dateString`. This is needed when `dateString` includes a month or day name and its locale format differs
|
|
* from the locale of this machine.
|
|
* @returns formatted date string or null if `dateString` is not a valid date
|
|
*/
|
|
format(dateString: string | null | undefined, dateFormat?: string, locale: string = 'en'): string | null {
|
|
if (!dateString) {
|
|
return null;
|
|
}
|
|
|
|
let date: moment.Moment;
|
|
|
|
if (!dateFormat) {
|
|
date = this.parseWithoutFormat(dateString);
|
|
} else {
|
|
date = momentFn(dateString, dateFormat, locale);
|
|
}
|
|
|
|
// format date (if it is valid)
|
|
return date.isValid() ? date.locale(this.locale).format(this.toFormat) : null;
|
|
}
|
|
|
|
private parseWithoutFormat(dateString: string): moment.Moment {
|
|
// reading date formats other than C2822 or ISO with moment is deprecated
|
|
// see https://momentjs.com/docs/#/parsing/string/
|
|
if (this.hasMomentFormat(dateString)) {
|
|
// expect C2822 or ISO format
|
|
return momentFn(dateString);
|
|
}
|
|
|
|
// fall back to native Date parsing for unknown formats
|
|
return momentFn(new Date(dateString));
|
|
}
|
|
|
|
private hasMomentFormat(dateString: string): boolean {
|
|
const date = momentFn(dateString, [moment.ISO_8601, DateFormatter.RFC2822_FORMAT], true); // strict mode
|
|
return date.isValid();
|
|
}
|
|
}
|