"use strict"; function padLeft(val, len) { return String(val).padStart(len || 2, "0"); } function dateTimeFormat(date, opts) { return new Intl.DateTimeFormat("en-US", opts).format(date); } function getOrdinalSuffix(day) { if (day > 3 && day < 21) { return "th"; } switch (day % 10) { case 1: return "st"; case 2: return "nd"; case 3: return "rd"; default: return "th"; } } function timezone(date, together) { let offset = date.getTimezoneOffset(); let prefix; if (offset <= 0) { prefix = "+"; offset = Math.abs(offset); } else { prefix = "-"; } return `${prefix}${padLeft(Math.floor(offset / 60))}${together ? "" : ":"}${padLeft(Math.floor(offset % 60))}`; } const FORMAT_MAP = { // 年份 yyyy: (d) => d.getFullYear(), YYYY: (d) => d.getFullYear(), YY: (d) => padLeft(d.getFullYear() % 100), // 月份 MMMM: (d) => dateTimeFormat(d, { month: "long" }), MMM: (d) => dateTimeFormat(d, { month: "short" }), MM: (d) => padLeft(d.getMonth() + 1), M: (d) => d.getMonth() + 1, // 日期 DD: (d) => padLeft(d.getDate()), D: (d) => d.getDate(), Do: (d) => { const day = d.getDate(); return String(day) + getOrdinalSuffix(day); }, // 星期 dddd: (d) => dateTimeFormat(d, { weekday: "long" }), ddd: (d) => dateTimeFormat(d, { weekday: "short" }), dd: (d) => dateTimeFormat(d, { weekday: "narrow" }), // 时间 HH: (d) => padLeft(d.getHours()), H: (d) => d.getHours(), hh: (d) => padLeft(d.getHours() % 12 || 12), h: (d) => d.getHours() % 12 || 12, mm: (d) => padLeft(d.getMinutes()), m: (d) => d.getMinutes(), ss: (d) => padLeft(d.getSeconds()), s: (d) => d.getSeconds(), SSS: (d) => padLeft(d.getMilliseconds(), 3), // 其他 A: (d) => d.getHours() >= 12 ? "PM" : "AM", a: (d) => d.getHours() >= 12 ? "pm" : "am", Z: (d) => timezone(d), ZZ: (d) => timezone(d, true) }; const tokens = Object.keys(FORMAT_MAP).sort((a, b) => b.length - a.length).join("|"); const pattern = new RegExp( `${tokens}|\\[([^\\]]*)]`, "g" ); function format(date, formatString) { if (!formatString || formatString === "ISO") { return date.toISOString(); } return formatString.replace(pattern, (match, escapeContent) => { if (escapeContent) { return escapeContent; } const formatter = FORMAT_MAP[match]; return formatter ? formatter(date) : match; }); } module.exports = format;