如何自定义date-fns的formatDistance实现特定场景日期显示格式
实现自定义日期显示规则(当天/昨天/一周内/超过一个月)
你可以通过分条件判断日期区间来实现这个自定义显示规则,不用依赖formatDistance(它更适合显示相对时长,比如"3小时前")。下面提供两种实现方案:
方案一:使用date-fns(推荐,简洁可靠)
借助date-fns的工具函数可以避免手动处理时间边界的坑,代码更清晰:
import { format, isToday, isYesterday, differenceInCalendarDays, differenceInCalendarMonths, parseISO } from 'date-fns'; import { zhCN } from 'date-fns/locale'; // 中文环境用这个locale,对应「周五」「昨天」这类文案 function formatCustomDate(wroteTime) { const targetDate = parseISO(wroteTime); // 解析后端返回的ISO格式日期 const now = new Date(); // 当天:仅显示时分 if (isToday(targetDate)) { return format(targetDate, 'HH:mm'); } // 昨天:显示「昨天 时分」 if (isYesterday(targetDate)) { return `昨天 ${format(targetDate, 'HH:mm')}`; } // 一周内(不含今天、昨天):显示「星期 时分」 const dayDiff = differenceInCalendarDays(now, targetDate); if (dayDiff > 1 && dayDiff <= 7) { return format(targetDate, 'ccc HH:mm', { locale: zhCN }); // ccc是星期简写,比如「周五」 } // 超过一个月:显示MM/DD/YYYY const monthDiff = differenceInCalendarMonths(now, targetDate); if (monthDiff >= 1) { return format(targetDate, 'MM/dd/yyyy'); } // 一周到一个月之间的情况(用户未明确,这里默认用MM/DD/YYYY,可按需调整) return format(targetDate, 'MM/dd/yyyy'); }
代码说明:
parseISO:比直接new Date()更可靠地解析ISO格式日期字符串isToday/isYesterday:直接判断日期是否为今天/昨天,无需手动计算时间戳ccc格式符:在中文locale下会返回「周一」「周五」这类星期简写differenceInCalendarMonths:按自然月份计算差值,比用30天近似更准确
方案二:原生JavaScript实现(无依赖)
如果不想引入第三方库,可以用原生JS手动处理:
function formatCustomDate(wroteTime) { const targetDate = new Date(wroteTime); const now = new Date(); // 转换为当天0点,用于判断今天/昨天 const targetMidnight = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()); const nowMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const oneDayMs = 24 * 60 * 60 * 1000; const timeDiff = nowMidnight - targetMidnight; // 格式化时分的工具函数 const formatTime = (date) => { return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; }; // 星期简写映射 const weekShortNames = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; // 当天 if (timeDiff === 0) { return formatTime(targetDate); } // 昨天 if (timeDiff === oneDayMs) { return `昨天 ${formatTime(targetDate)}`; } // 一周内 if (timeDiff > oneDayMs && timeDiff <= 7 * oneDayMs) { const weekIndex = targetDate.getDay(); return `${weekShortNames[weekIndex]} ${formatTime(targetDate)}`; } // 判断是否超过一个月 const isOverOneMonth = now.getFullYear() > targetDate.getFullYear() || (now.getFullYear() === targetDate.getFullYear() && now.getMonth() - targetDate.getMonth() >= 1); // 超过一个月:显示MM/DD/YYYY if (isOverOneMonth) { const month = (targetDate.getMonth() + 1).toString().padStart(2, '0'); const day = targetDate.getDate().toString().padStart(2, '0'); return `${month}/${day}/${targetDate.getFullYear()}`; } // 一周到一个月之间的默认处理 const month = (targetDate.getMonth() + 1).toString().padStart(2, '0'); const day = targetDate.getDate().toString().padStart(2, '0'); return `${month}/${day}/${targetDate.getFullYear()}`; }
使用方式:
直接调用函数传入后端返回的日期字符串即可:
const displayDate = formatCustomDate('2022-10-20T10:41:31.095'); console.log(displayDate); // 根据当前日期会输出对应格式
内容的提问来源于stack exchange,提问作者Гришко Шкарта
相关产品推荐
相关产品推荐

