/** 可读化时差 (date2 - date1) * @param options.fuzzy 模糊化大于“天”以内内的时间,都显示为 “不久前”,如 “40 分钟” 前会显示为 “不久前” * @example * readableDateDiff(new Date(), new Date('2020-01-01')) // 1 年前 * readableDateDiff(new Date(), new Date('2020-01-01')) // 12 天前 * readableDateDiff(new Date(), new Date('2020-01-01')) // 3 月前 * */ const I18N = { zh: { y: " 年前", M: " 月前", d: " 天前", h: " 小时前", m: " 分钟前", s: " 秒前", ss: "几秒前", fuzzy: "不久前", _y: " 年后", _M: " 月后", _d: " 天后", _h: " 小时后", _m: " 分钟后", _s: " 秒后", _ss: "几秒后", _fuzzy: "不久后", }, en: { y: " years ago", M: " months ago", d: " days ago", h: " hours ago", m: " minutes ago", s: " seconds ago", fuzzy: "just now", _y: " years later", _M: " months later", _d: " days later", _h: " hours later", _m: " minutes later", _s: "seconds later", _fuzzy: "just later", }, } export function readableDateDiff( date1: Date | string, date2: Date | string, options?: { /** 模糊 */ fuzzy?: boolean /** 模糊秒 */ fuzzySecond?: boolean /** i18n 语言 */ i18n?: keyof typeof I18N /** 在 10 秒误差内, 保证 date1 > date2,用于客户端之间时间误差不会出现当前时间小于目标时间的情况*/ ensureDate1Bigger?: boolean } ) { let t1 = new Date(date1).getTime() let t2 = new Date(date2).getTime() if (options?.ensureDate1Bigger && t1 < t2 && Math.abs(t1 - t2) < 10 * 1000) { t1 = t2 } let diff = Math.abs(t1 - t2) let direction = t1 >= t2 ? "" : "_" let ms = diff let s = ms / 1000 let m = s / 60 let h = m / 60 let d = h / 24 let M = d / 30 let y = M / 12 let lang = options?.i18n || "zh" let Dict: any = I18N[lang] if (s < 60) { if (options?.fuzzy) { return Dict[direction + "fuzzy"] } else { let ft = Math.trunc(s) if (options?.fuzzySecond && ft < 60) { return Dict[direction + "ss"] } else { return Math.trunc(s) + Dict[direction + "s"] } } } else if (m < 60) { if (options?.fuzzy) { return Dict[direction + "fuzzy"] } else { return Math.trunc(m) + Dict[direction + "m"] } } else if (h < 24) { if (options?.fuzzy) { return Dict[direction + "fuzzy"] } else { return Math.trunc(h) + Dict[direction + "h"] } } else if (d < 30) { return Math.trunc(d) + Dict[direction + "d"] } else if (M < 12) { return Math.trunc(M) + Dict[direction + "M"] } else { return Math.trunc(y) + Dict[direction + "y"] } }