const STANDARD = Math.pow(10, 12); const ONE_DAY_TICKS = 86400000; const ONE_MINUTE_TICKS = 60 * 1000; const ONE_HOUR_TICKS = 60 * 60 * 1000; export const enum TimeFormatRule { /** * 12小时制 */ Hour12, /** * 24小时制 */ Hour24, } function formatHour2Friendly(hour: number) { if (hour <= 1) { return "凌晨"; } if (hour < 12) { return "上午"; } if (hour === 12) { return "中午"; } if (hour < 20) { return "下午"; } return "晚上"; } function formatHour12Unit(hour: number, rule: TimeFormatRule) { if (rule === TimeFormatRule.Hour12) { return hour > 12 ? hour - 12 : hour; } return hour; } function format2DetailTime(hour: number, time: Date, rule: TimeFormatRule) { let hourString = ""; const h = formatHour12Unit(hour, rule); if (h < 10) { hourString = "0" + h; } else { hourString = h + ""; } let minuteString = ""; const m = time.getMinutes(); if (m < 10) { minuteString = "0" + m; } else { minuteString = "" + m; } return `${formatHour2Friendly(hour)} ${hourString}:${minuteString}`; } function isSameDay(d1: Date, d2: Date) { return ( d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate() ); } function isInMinute(d1: Date, d2: Date) { return Math.abs(d1.valueOf() - d2.valueOf()) <= ONE_MINUTE_TICKS; } function isInHour(d1: Date, d2: Date) { return Math.abs(d1.valueOf() - d2.valueOf()) < ONE_HOUR_TICKS; } function isYesterday(date: Date) { const now = new Date(); now.setHours(0); now.setMinutes(0); now.setSeconds(0); now.setMilliseconds(0); const ticks = now.valueOf(); const yesterday = ticks - ONE_DAY_TICKS; const v = date.valueOf(); return v >= yesterday && v < ticks; } function isIn6Days(date: Date) { const now = new Date(); now.setHours(0); now.setMinutes(0); now.setSeconds(0); now.setMilliseconds(0); const ticks = now.valueOf(); const sixDaysAgo = ticks - ONE_DAY_TICKS * 6; const v = date.valueOf(); return v >= sixDaysAgo && v < ticks; } function isSameYear(d1: Date, d2: Date) { return d1.getFullYear() === d2.getFullYear(); } const DAY_MAPPING: { [key: number]: string } = { 0: "日", 1: "一", 2: "二", 3: "三", 4: "四", 5: "五", 6: "六", }; function getDayInWeek(time: Date) { const d = time.getDay(); return DAY_MAPPING[d]; } function formatWithTwoNumber(number: number) { return number < 10 ? `0${number}` : `${number}`; } function formatTime2MonthDate(time: Date) { return `${formatWithTwoNumber(time.getMonth() + 1)}月${formatWithTwoNumber( time.getDate() )}日`; } function formatTime2ShortMonthDate(time: Date) { return `${formatWithTwoNumber(time.getMonth() + 1)}/${formatWithTwoNumber( time.getDate() )}`; } function formatTime2YearMonthDate(time: Date) { return `${time.getFullYear()}年${formatWithTwoNumber( time.getMonth() + 1 )}月${formatWithTwoNumber(time.getDate())}日`; } function formatTime2ShortYearMonthDate(time: Date) { return `${time.getFullYear()}/${formatWithTwoNumber( time.getMonth() + 1 )}/${formatWithTwoNumber(time.getDate())}`; } /** * 格式化时间。 short模式下格式 * * 刚刚(1分钟内) [在short模式下不生效] * * {x}分钟前 [在short模式下不生效] * * 今天,格式化为:[上午|中午|下午] hh:mm | [两者一致] * 昨天,格式化为:昨天 [上午|中午|下午] hh:mm | 昨天 * 2~6天前,格式化为:星期几 [上午|中午|下午] hh:mm | 星期几 * 同年时间,格式化为:07月08日 [上午|中午|下午] hh:mm | 07/12 * 非同年时间,格式化为:2019年07月08日 [上午|中午|下午] hh:mm | 2019/01/02 * @param time Javascript标准时间 * @param option { rule: 选择是12小时制还是24小时制,short:是否以短时间形式显示 } */ export function formatTime( time: number, option = { rule: TimeFormatRule.Hour12, short: false } ) { if (time < STANDARD) { time *= 1000; } const t = new Date(time); const now = new Date(); if (!option.short) { if (isInMinute(t, now)) { return "刚刚"; } if (isInHour(t, now)) { return `${Math.round( Math.abs(t.valueOf() - now.valueOf()) / 1000 / 60 )}分钟前`; } } const hour = t.getHours(); if (isSameDay(t, now)) { return format2DetailTime(hour, t, option.rule); } if (isYesterday(t)) { if (option.short) { return "昨天"; } return "昨天 " + format2DetailTime(hour, t, option.rule); } if (isIn6Days(t)) { if (option.short) { return `星期${getDayInWeek(t)}`; } return ( `星期${getDayInWeek(t)} ` + format2DetailTime(hour, t, option.rule) ); } if (isSameYear(t, now)) { if (option.short) { return formatTime2ShortMonthDate(t); } return ( formatTime2MonthDate(t) + " " + format2DetailTime(hour, t, option.rule) ); } if (option.short) { return formatTime2ShortYearMonthDate(t); } return ( formatTime2YearMonthDate(t) + " " + format2DetailTime(hour, t, option.rule) ); }