You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Intl.RelativeTimeFormat实现双单位相对时间格式化函数

实现支持双时间单位的本地化相对时间函数

要实现支持两个时间单位的相对时间格式(如“2小时15分钟后”“1天6小时前”),同时保留Intl.RelativeTimeFormat的本地化能力,我们可以对原有函数做以下修改:

核心改动思路

  1. 不再只返回单个最大单位,而是提取最大有效单位和次一级有效单位,拼接两个本地化后的时间片段
  2. 修正时间单位计算逻辑,取整数部分而非四舍五入,避免出现“1天-2小时”这类不合理结果
  3. 统一处理未来/过去的时间差,无需拆分正负分支
  4. 处理边界情况:当次一级单位为0时仅返回单个单位;时间差为0时返回“刚刚”

修改后的完整代码

const fromNow = function (timestamp, locale = navigator.language) {
  const now = Date.now();
  const diff = timestamp - now;
  const absDiff = Math.abs(diff);
  
  // 计算各时间单位的整数部分,保留正负符号
  const days = Math.trunc(diff / (1000 * 60 * 60 * 24));
  const hours = Math.trunc((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  const minutes = Math.trunc((diff % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.trunc((diff % (1000 * 60)) / 1000);
  
  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'always' });
  const parts = [];

  // 优先取最大的有效单位,再取次一级单位
  if (absDiff >= 1000 * 60 * 60 * 24) {
    parts.push(rtf.format(days, 'day'));
    // 仅当小时数不为0时添加小时部分
    if (Math.abs(hours) > 0) {
      parts.push(rtf.format(hours, 'hour').replace(/^[+-]?\d+ /, ''));
    }
  } else if (absDiff >= 1000 * 60 * 60) {
    parts.push(rtf.format(hours, 'hour'));
    if (Math.abs(minutes) > 0) {
      parts.push(rtf.format(minutes, 'minute').replace(/^[+-]?\d+ /, ''));
    }
  } else if (absDiff >= 1000 * 60) {
    parts.push(rtf.format(minutes, 'minute'));
    if (Math.abs(seconds) > 0) {
      parts.push(rtf.format(seconds, 'second').replace(/^[+-]?\d+ /, ''));
    }
  } else {
    // 小于1分钟时,仅显示秒数或"刚刚"
    return absDiff < 1000 ? '刚刚' : rtf.format(seconds, 'second');
  }

  // 拼接结果,自动适配本地化格式
  return parts.join(' ');
};

export default fromNow;

关键细节说明

  • 本地化支持:通过传入locale参数(默认使用浏览器语言),Intl.RelativeTimeFormat会自动生成对应语言的相对时间描述(比如英文环境会返回"2 days 6 hours ago")
  • 单位处理:使用Math.trunc取整数部分,确保时间单位为完整数值;拼接次一级单位时,通过正则去掉重复的正负前缀和数字,只保留单位描述(比如从"6 hours"提取"hours")
  • 边界处理:当时间差小于1秒时返回“刚刚”,避免显示“0秒后/前”这类不自然的描述;次一级单位为0时不显示,比如刚好2天则返回“2天后”而非“2天0小时后”

示例输出

  • 未来2小时15分钟:fromNow(Date.now() + 2*3600*1000 + 15*60*1000) → 2小时15分钟后(中文环境)
  • 过去1天6小时:fromNow(Date.now() - 24*3600*1000 - 6*3600*1000) → 1天6小时前(中文环境)
  • 刚好3天:fromNow(Date.now() + 3*24*3600*1000) → 3天后(中文环境)

内容的提问来源于stack exchange,提问作者Julien Reszka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:40:21