258 lines
6.3 KiB
TypeScript
258 lines
6.3 KiB
TypeScript
import type { Dayjs, OpUnitType } from 'dayjs';
|
|
|
|
import dayjs from 'dayjs';
|
|
import duration from 'dayjs/plugin/duration';
|
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @Docs
|
|
* https://day.js.org/docs/en/display/format
|
|
*/
|
|
|
|
/**
|
|
* Default timezones
|
|
* https://day.js.org/docs/en/timezone/set-default-timezone#docsNav
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* UTC
|
|
* https://day.js.org/docs/en/plugin/utc
|
|
* @install
|
|
* import utc from 'dayjs/plugin/utc';
|
|
* dayjs.extend(utc);
|
|
* @usage
|
|
* dayjs().utc().format()
|
|
*
|
|
*/
|
|
|
|
dayjs.extend(duration);
|
|
dayjs.extend(relativeTime);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
export type DatePickerFormat = Dayjs | Date | string | number | null | undefined;
|
|
|
|
export const formatPatterns = {
|
|
dateTime: 'DD MMM YYYY h:mm a', // 17 Apr 2022 12:00 am
|
|
date: 'DD MMM YYYY', // 17 Apr 2022
|
|
time: 'h:mm a', // 12:00 am
|
|
split: {
|
|
dateTime: 'DD/MM/YYYY h:mm a', // 17/04/2022 12:00 am
|
|
date: 'DD/MM/YYYY', // 17/04/2022
|
|
},
|
|
paramCase: {
|
|
dateTime: 'DD-MM-YYYY h:mm a', // 17-04-2022 12:00 am
|
|
date: 'DD-MM-YYYY', // 17-04-2022
|
|
},
|
|
};
|
|
|
|
const isValidDate = (date: DatePickerFormat) => date !== null && date !== undefined && dayjs(date).isValid();
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
export function today(template?: string): string {
|
|
return dayjs(new Date()).startOf('day').format(template);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output 17 Apr 2022 12:00 am
|
|
*/
|
|
export function fDateTime(date: DatePickerFormat, template?: string): string {
|
|
if (!isValidDate(date)) {
|
|
return 'Invalid date';
|
|
}
|
|
|
|
return dayjs(date).format(template ?? formatPatterns.dateTime);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output 17 Apr 2022
|
|
*/
|
|
export function fDate(date: DatePickerFormat, template?: string): string {
|
|
if (!isValidDate(date)) {
|
|
return 'Invalid date';
|
|
}
|
|
|
|
return dayjs(date).format(template ?? formatPatterns.date);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output 12:00 am
|
|
*/
|
|
export function fTime(date: DatePickerFormat, template?: string): string {
|
|
if (!isValidDate(date)) {
|
|
return 'Invalid date';
|
|
}
|
|
|
|
return dayjs(date).format(template ?? formatPatterns.time);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output 1713250100
|
|
*/
|
|
export function fTimestamp(date: DatePickerFormat): number | 'Invalid date' {
|
|
if (!isValidDate(date)) {
|
|
return 'Invalid date';
|
|
}
|
|
|
|
return dayjs(date).valueOf();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output a few seconds, 2 years
|
|
*/
|
|
export function fToNow(date: DatePickerFormat): string {
|
|
if (!isValidDate(date)) {
|
|
return 'Invalid date';
|
|
}
|
|
|
|
return dayjs(date).toNow(true);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output boolean
|
|
*/
|
|
export function fIsBetween(inputDate: DatePickerFormat, startDate: DatePickerFormat, endDate: DatePickerFormat): boolean {
|
|
if (!isValidDate(inputDate) || !isValidDate(startDate) || !isValidDate(endDate)) {
|
|
return false;
|
|
}
|
|
|
|
const formattedInputDate = fTimestamp(inputDate);
|
|
const formattedStartDate = fTimestamp(startDate);
|
|
const formattedEndDate = fTimestamp(endDate);
|
|
|
|
if (formattedInputDate === 'Invalid date' || formattedStartDate === 'Invalid date' || formattedEndDate === 'Invalid date') {
|
|
return false;
|
|
}
|
|
|
|
return formattedInputDate >= formattedStartDate && formattedInputDate <= formattedEndDate;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output boolean
|
|
*/
|
|
export function fIsAfter(startDate: DatePickerFormat, endDate: DatePickerFormat): boolean {
|
|
if (!isValidDate(startDate) || !isValidDate(endDate)) {
|
|
return false;
|
|
}
|
|
|
|
return dayjs(startDate).isAfter(endDate);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output boolean
|
|
*/
|
|
export function fIsSame(startDate: DatePickerFormat, endDate: DatePickerFormat, unitToCompare?: OpUnitType): boolean {
|
|
if (!isValidDate(startDate) || !isValidDate(endDate)) {
|
|
return false;
|
|
}
|
|
|
|
return dayjs(startDate).isSame(endDate, unitToCompare ?? 'year');
|
|
}
|
|
|
|
/**
|
|
* @output
|
|
* Same day: 26 Apr 2024
|
|
* Same month: 25 - 26 Apr 2024
|
|
* Same month: 25 - 26 Apr 2024
|
|
* Same year: 25 Apr - 26 May 2024
|
|
*/
|
|
export function fDateRangeShortLabel(startDate: DatePickerFormat, endDate: DatePickerFormat, initial?: boolean): string {
|
|
if (!isValidDate(startDate) || !isValidDate(endDate) || fIsAfter(startDate, endDate)) {
|
|
return 'Invalid date';
|
|
}
|
|
|
|
let label = `${fDate(startDate)} - ${fDate(endDate)}`;
|
|
|
|
if (initial) {
|
|
return label;
|
|
}
|
|
|
|
const isSameYear = fIsSame(startDate, endDate, 'year');
|
|
const isSameMonth = fIsSame(startDate, endDate, 'month');
|
|
const isSameDay = fIsSame(startDate, endDate, 'day');
|
|
|
|
if (isSameYear && !isSameMonth) {
|
|
label = `${fDate(startDate, 'DD MMM')} - ${fDate(endDate)}`;
|
|
} else if (isSameYear && isSameMonth && !isSameDay) {
|
|
label = `${fDate(startDate, 'DD')} - ${fDate(endDate)}`;
|
|
} else if (isSameYear && isSameMonth && isSameDay) {
|
|
label = `${fDate(endDate)}`;
|
|
}
|
|
|
|
return label;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* @output 2024-05-28T05:55:31+00:00
|
|
*/
|
|
export type DurationProps = {
|
|
years?: number;
|
|
months?: number;
|
|
days?: number;
|
|
hours?: number;
|
|
minutes?: number;
|
|
seconds?: number;
|
|
milliseconds?: number;
|
|
};
|
|
|
|
export function fAdd({ years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0 }: DurationProps) {
|
|
const result = dayjs()
|
|
.add(
|
|
dayjs.duration({
|
|
years,
|
|
months,
|
|
days,
|
|
hours,
|
|
minutes,
|
|
seconds,
|
|
milliseconds,
|
|
})
|
|
)
|
|
.format();
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @output 2024-05-28T05:55:31+00:00
|
|
*/
|
|
export function fSub({ years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0 }: DurationProps) {
|
|
const result = dayjs()
|
|
.subtract(
|
|
dayjs.duration({
|
|
years,
|
|
months,
|
|
days,
|
|
hours,
|
|
minutes,
|
|
seconds,
|
|
milliseconds,
|
|
})
|
|
)
|
|
.format();
|
|
|
|
return result;
|
|
}
|