190 lines
6.8 KiB
TypeScript
190 lines
6.8 KiB
TypeScript
import { differenceInDays, format, formatDistanceToNow, startOfDay, startOfMinute, startOfMonth, startOfWeek, startOfYear } from "date-fns";
|
|
|
|
export type DateFormatType = "YYYY-MM-DD" | "DD-MM-YYYY" | "MM-DD-YYYY" | "diff";
|
|
export const DateFormats: { name: string; value: DateFormatType; labelKey: string }[] = [
|
|
{ name: "YYYY-MM-DD", value: "YYYY-MM-DD", labelKey: "formats.date.ymd" },
|
|
{ name: "DD-MM-YYYY", value: "DD-MM-YYYY", labelKey: "formats.date.dmy" },
|
|
{ name: "MM-DD-YYYY", value: "MM-DD-YYYY", labelKey: "formats.date.mdy" },
|
|
{ name: "Difference", value: "diff", labelKey: "formats.date.diff" },
|
|
];
|
|
export type DateDisplay = "ymd" | "ago" | "dm" | "mdy" | "hms" | "ymdhms" | "ymdhmsms";
|
|
|
|
const coerce = (value: Date | string | null | undefined): Date => {
|
|
if (value === null || value === undefined) return new Date();
|
|
return value instanceof Date ? value : new Date(value);
|
|
};
|
|
|
|
const fmt = (value: Date | string | null | undefined, pattern: string): string => {
|
|
return format(coerce(value), pattern);
|
|
};
|
|
|
|
const dateAgo = (value: Date | string | null | undefined): string => {
|
|
const at = coerce(value);
|
|
const days = Math.abs(differenceInDays(new Date(), at));
|
|
if (days <= 1) {
|
|
return formatDistanceToNow(startOfMinute(at), { addSuffix: true });
|
|
} else if (days <= 7) {
|
|
return formatDistanceToNow(startOfDay(at), { addSuffix: true });
|
|
} else if (days <= 30) {
|
|
return formatDistanceToNow(startOfWeek(at), { addSuffix: true });
|
|
} else if (days <= 30 * 12) {
|
|
return formatDistanceToNow(startOfMonth(at), { addSuffix: true });
|
|
} else if (days <= 30 * 12 * 2) {
|
|
return formatDistanceToNow(startOfYear(at), { addSuffix: true });
|
|
} else {
|
|
return fmt(at, "yyyy-MM-dd");
|
|
}
|
|
};
|
|
const dateYMD = (value: Date | string | null | undefined): string => fmt(value, "yyyy-MM-dd");
|
|
const dateDMY = (value: Date | string | null | undefined): string => fmt(value, "dd-MM-yyyy");
|
|
const dateMDY = (value: Date | string | null | undefined): string => fmt(value, "MM-dd-yyyy");
|
|
const dateLL = (value: Date | string | null | undefined): string => fmt(value, "yyyy-MM-dd");
|
|
const dateYMDHM = (value: Date | string | null | undefined): string => fmt(value, "yyyy-MM-dd HH:mm");
|
|
const dateYMDHMS = (value: Date | string | null | undefined): string => fmt(value, "yyyy-MM-dd HH:mm:ss");
|
|
const dateYMDHMSMS = (value: Date | string | null | undefined): string => fmt(value, "yyyy-MM-dd HH:mm:ss.SSS");
|
|
const dateMonthName = (value: Date | string | null | undefined): string => fmt(value, "MMMM yyyy");
|
|
const dateDM = (value: Date | string | null | undefined): string => fmt(value, "d MMM");
|
|
const dateMonthDayYear = (value: Date | string | null | undefined): string => fmt(value, "MMMM d, yyyy");
|
|
const dateMonthDay = (value: Date | string | null | undefined): string => fmt(value, "MMM d");
|
|
const dateHMS = (value: Date | string | null | undefined): string => fmt(value, "HH:mm:ss");
|
|
|
|
const daysFromDate = (value: Date, days: number) => {
|
|
return new Date(new Date().setDate(value.getDate() + days));
|
|
};
|
|
|
|
const diffDays = (a: Date, b: Date) => {
|
|
const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
|
|
const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
|
|
|
|
const _MS_PER_DAY = 1000 * 60 * 60 * 24;
|
|
return (utc2 - utc1) / _MS_PER_DAY;
|
|
};
|
|
|
|
const add = (value: Date, days: number) => {
|
|
return new Date(new Date().setDate(value.getDate() + days));
|
|
};
|
|
|
|
const getMonths = () => {
|
|
return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
};
|
|
|
|
const getMonthName = (month: number): string => {
|
|
const months: string[] = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
if (month >= 1 && month <= 12) {
|
|
return months[month - 1].substring(0, 3);
|
|
}
|
|
return "";
|
|
};
|
|
|
|
const isCurrentMonth = (year: number, month: number): boolean => {
|
|
const today = new Date();
|
|
return today.getFullYear() === year && today.getMonth() + 1 === month;
|
|
};
|
|
|
|
const gteFromFilter = (filter: string, from?: Date) => {
|
|
let gte: Date | undefined = undefined;
|
|
if (!from) {
|
|
from = new Date();
|
|
}
|
|
|
|
if (filter === "all-time") {
|
|
gte = undefined;
|
|
} else if (filter === "last-24-hours") {
|
|
gte = daysFromDate(from, 1 * -1);
|
|
} else if (filter === "last-7-days") {
|
|
gte = daysFromDate(from, 7 * -1);
|
|
} else if (filter === "last-30-days") {
|
|
gte = daysFromDate(from, 30 * -1);
|
|
} else if (filter === "last-3-months") {
|
|
gte = daysFromDate(from, 30 * 3 * -1);
|
|
} else if (filter === "last-6-months") {
|
|
gte = daysFromDate(from, 30 * 6 * -1);
|
|
} else if (filter === "last-year") {
|
|
gte = daysFromDate(from, 30 * 12 * -1);
|
|
} else if (filter === "year-to-date") {
|
|
gte = new Date(from.getFullYear(), 0, 1);
|
|
} else if (filter === "month-to-date") {
|
|
gte = new Date(from.getFullYear(), from.getMonth(), 1);
|
|
} else if (filter === "week-to-date") {
|
|
gte = new Date(from.getFullYear(), from.getMonth(), from.getDate() - from.getDay());
|
|
} else if (filter === "last-hour") {
|
|
gte = new Date(from.getTime() - 60 * 60 * 1000);
|
|
} else if (filter === "last-10-minutes") {
|
|
gte = new Date(from.getTime() - 10 * 60 * 1000);
|
|
}
|
|
return gte;
|
|
};
|
|
|
|
const getDuration = ({ start, end, format = "s" }: { start: Date; end: Date; format: "ms" | "s" | "m" | "h" | "d" | "w" | "M" | "y" }) => {
|
|
const diff = +new Date(end) - +new Date(start);
|
|
const seconds = Math.floor(diff / 1000);
|
|
switch (format) {
|
|
case "ms":
|
|
return diff;
|
|
case "s":
|
|
return seconds;
|
|
case "m":
|
|
return Math.floor(seconds / 60);
|
|
case "h":
|
|
return Math.floor(seconds / 3600);
|
|
case "d":
|
|
return Math.floor(seconds / 86400);
|
|
case "w":
|
|
return Math.floor(seconds / 604800);
|
|
case "M":
|
|
return Math.floor(seconds / 2592000);
|
|
case "y":
|
|
return Math.floor(seconds / 31536000);
|
|
default:
|
|
return diff;
|
|
}
|
|
};
|
|
|
|
function getDurationInSeconds({ start, end }: { start: Date | null; end: Date | null }) {
|
|
if (start && end) {
|
|
const diff = +new Date(end) - +new Date(start);
|
|
const seconds = Math.floor(diff / 1000);
|
|
|
|
if (seconds < 60) {
|
|
return `${seconds}s`;
|
|
} else {
|
|
return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
}
|
|
}
|
|
return "-";
|
|
}
|
|
|
|
function getDateStartOfDay(date: Date) {
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
|
|
}
|
|
function getDateEndOfDay(date: Date) {
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
|
|
}
|
|
|
|
export default {
|
|
dateAgo,
|
|
dateYMD,
|
|
dateDMY,
|
|
dateMDY,
|
|
dateLL,
|
|
dateYMDHM,
|
|
dateYMDHMS,
|
|
dateYMDHMSMS,
|
|
dateMonthName,
|
|
dateDM,
|
|
dateHMS,
|
|
dateMonthDayYear,
|
|
dateMonthDay,
|
|
daysFromDate,
|
|
diffDays,
|
|
add,
|
|
getMonths,
|
|
getMonthName,
|
|
isCurrentMonth,
|
|
gteFromFilter,
|
|
getDuration,
|
|
getDurationInSeconds,
|
|
getDateStartOfDay,
|
|
getDateEndOfDay,
|
|
};
|