UNPKG

@cch137/format-utils

Version:

A collection of utility modules for formatting and processing data

147 lines (146 loc) 5.04 kB
const tokenConverterMap = (() => { const fullMonthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ]; const abbvMonthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ]; const fullDayNames = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ]; const abbvDayNames = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", ]; const padStart = (val, len = 2) => String(val).padStart(len, "0"); const getY = (date, isUTC) => isUTC ? date.getUTCFullYear() : date.getFullYear(); const getH24 = (date, isUTC) => isUTC ? date.getUTCHours() : date.getHours(); const getH12 = (date, isUTC) => (isUTC ? date.getUTCHours() : date.getHours()) % 12; const getMin = (date, isUTC) => isUTC ? date.getUTCMinutes() : date.getMinutes(); const getSec = (date, isUTC) => isUTC ? date.getUTCSeconds() : date.getSeconds(); const getF = (date, isUTC) => isUTC ? date.getUTCMilliseconds() : date.getMilliseconds(); const getDay = (date, isUTC) => isUTC ? date.getUTCDay() : date.getDay(); const getDate = (date, isUTC) => isUTC ? date.getUTCDate() : date.getDate(); const getMonth = (date, isUTC) => (isUTC ? date.getUTCMonth() : date.getMonth()) + 1; const returnString = (f) => (date, isUTC) => String(f(date, isUTC)); return [ ["yyyy", (d, u) => padStart(getY(d, u), 4)], ["yy", (d, u) => padStart(getY(d, u))], ["y", returnString(getY)], ["HH", (d, u) => padStart(getH24(d, u))], ["H", returnString(getH24)], ["hh", (d, u) => padStart(getH12(d, u))], ["h", returnString(getH12)], ["mm", (d, u) => padStart(getMin(d, u))], ["m", returnString(getMin)], ["ss", (d, u) => padStart(getSec(d, u))], ["s", returnString(getSec)], ["fff", (d, u) => padStart(getF(d, u), 3)], ["ff", (d, u) => padStart(Math.round(getF(d, u) / 10))], ["f", (d, u) => String(Math.round(getF(d, u) / 100))], ["tt", (d, u) => (getH24(d, u) < 12 ? "am" : "pm")], ["t", (d, u) => (getH24(d, u) < 12 ? "a" : "p")], ["TT", (d, u) => (getH24(d, u) < 12 ? "AM" : "PM")], ["T", (d, u) => (getH24(d, u) < 12 ? "A" : "P")], ["dddd", (d, u) => fullDayNames[getDay(d, u)]], ["DDD", (d, u) => abbvDayNames[getDay(d, u)].toUpperCase()], ["ddd", (d, u) => abbvDayNames[getDay(d, u)]], ["dd", (d, u) => padStart(getDate(d, u))], ["d", returnString(getDate)], ["MMMM", (d, u) => fullMonthNames[getMonth(d, u) - 1]], ["MMM", (d, u) => abbvMonthNames[getMonth(d, u) - 1].toUpperCase()], ["mmm", (d, u) => abbvMonthNames[getMonth(d, u) - 1]], ["MM", (d, u) => padStart(getMonth(d, u))], ["M", returnString(getMonth)], ]; })(); export function formatDate(date, format = "yyyy-MM-dd HH:mm:ss", isUTC = false) { const parts = []; while (format.length > 0) { const matched = tokenConverterMap.find(([token]) => format.startsWith(token)); if (!matched) { parts.push(format[0]); format = format.substring(1); continue; } const [token, converter] = matched; parts.push(converter(date, isUTC)); format = format.substring(token.length); } return parts.join(""); } export default formatDate; export function formatRelativeDate(date, locale = "en", dateFormatOptions = { year: "numeric", month: "2-digit", day: "2-digit", }) { if (!(date instanceof Date) || isNaN(date.getTime())) { throw new Error("Invalid date"); } const now = new Date(); const diffMs = now.getTime() - date.getTime(); const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); if (diffDays > 15) { const dtf = new Intl.DateTimeFormat(locale, dateFormatOptions); return dtf.format(date); } const diffSeconds = Math.floor(diffMs / 1000); const diffMinutes = Math.floor(diffSeconds / 60); const diffHours = Math.floor(diffMinutes / 60); const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto", style: "long", }); if (diffDays >= 2) { return rtf.format(-diffDays, "day"); } else if (diffDays === 1) { return rtf.format(-1, "day"); } else if (diffHours >= 1) { return rtf.format(-diffHours, "hour"); } else if (diffMinutes >= 1) { return rtf.format(-diffMinutes, "minute"); } else if (diffSeconds <= 1) { return "just now"; } else { return rtf.format(-diffSeconds, "second"); } }