【问题标题】:How to format time since xxx e.g. “4 minutes ago” similar to Stack Exchange sites如何格式化自 xxx 以来的时间,例如“4 分钟前”类似于 Stack Exchange 网站
【发布时间】:2022-01-19 14:34:47
【问题描述】:

问题是如何将 JavaScript Date 格式化为一个字符串,说明经过的时间,类似于您在 Stack Overflow 上看到的时间显示方式。

例如

  • 1 分钟前
  • 1 小时前
  • 1 天前
  • 1 个月前
  • 1 年前

【问题讨论】:

标签: javascript date-formatting


【解决方案1】:

function timeSince(date) {

  var seconds = Math.floor((new Date() - date) / 1000);

  var interval = seconds / 31536000;

  if (interval > 1) {
    return Math.floor(interval) + " years";
  }
  interval = seconds / 2592000;
  if (interval > 1) {
    return Math.floor(interval) + " months";
  }
  interval = seconds / 86400;
  if (interval > 1) {
    return Math.floor(interval) + " days";
  }
  interval = seconds / 3600;
  if (interval > 1) {
    return Math.floor(interval) + " hours";
  }
  interval = seconds / 60;
  if (interval > 1) {
    return Math.floor(interval) + " minutes";
  }
  return Math.floor(seconds) + " seconds";
}
var aDay = 24*60*60*1000;
console.log(timeSince(new Date(Date.now()-aDay)));
console.log(timeSince(new Date(Date.now()-aDay*2)));

【讨论】:

  • @hello - 是的,单点出口在不碍事时有它的优点。如今,那些过于认真的人误解了这句格言的起源。
  • 功能不错,但有些备注。将第一行更改为: var seconds = Math.floor(((new Date().getTime()/1000) - date)) 以使用 unix 时间戳。并且需要将 intval > 1 更改为 intval >=1 否则它会显示 75 分钟(1 到 2 小时之间)。
  • @PanMan 如果您只是将 > 更改为 >= 那么您最终会得到像“1 分钟”这样的时间。我发布了这个答案的修改版本,有条件地添加了“s”:stackoverflow.com/a/23259289/373655
  • 永远不要使用字符串连接,如果你想要一个可以国际化的解决方案,可以使用 String.format
  • 如果我想把它放在 div 类中怎么办?我能做些什么?对不起,我不是 javascript 的专家。我试过这个 document.getElementsByTagName('.sampleclass')[0].innerHTML = timeSince(date);而这个 document.getElementById('idname')[0].innerHTML = timeSince(date);但它不起作用。有什么帮助吗?谢谢。
【解决方案2】:

在这种情况下可能有点矫枉过正,但如果机会显示moment.js 真是太棒了!

Moment.js 是一个 javascript 日期时间库,要在这种情况下使用它,你可以这样做:

moment(yourdate).fromNow()

http://momentjs.com/docs/#/displaying/fromnow/

2018 年附录Luxon 是一个新的现代图书馆,可能值得一看!

【讨论】:

  • 您好,我正在使用您的答案来获取时间差异。如果我只需要日期的首字母,如 y、month 和 m 和 day 作为 d,我该怎么办?
  • 我怎样才能只用这个得到 D M s h 而不是几天前几个月前?
【解决方案3】:

这将向您显示过去和以前的时间格式,例如“2 天前”“10 分钟后”,您可以将日期对象、数字时间戳或日期字符串传递给它

function time_ago(time) {

  switch (typeof time) {
    case 'number':
      break;
    case 'string':
      time = +new Date(time);
      break;
    case 'object':
      if (time.constructor === Date) time = time.getTime();
      break;
    default:
      time = +new Date();
  }
  var time_formats = [
    [60, 'seconds', 1], // 60
    [120, '1 minute ago', '1 minute from now'], // 60*2
    [3600, 'minutes', 60], // 60*60, 60
    [7200, '1 hour ago', '1 hour from now'], // 60*60*2
    [86400, 'hours', 3600], // 60*60*24, 60*60
    [172800, 'Yesterday', 'Tomorrow'], // 60*60*24*2
    [604800, 'days', 86400], // 60*60*24*7, 60*60*24
    [1209600, 'Last week', 'Next week'], // 60*60*24*7*4*2
    [2419200, 'weeks', 604800], // 60*60*24*7*4, 60*60*24*7
    [4838400, 'Last month', 'Next month'], // 60*60*24*7*4*2
    [29030400, 'months', 2419200], // 60*60*24*7*4*12, 60*60*24*7*4
    [58060800, 'Last year', 'Next year'], // 60*60*24*7*4*12*2
    [2903040000, 'years', 29030400], // 60*60*24*7*4*12*100, 60*60*24*7*4*12
    [5806080000, 'Last century', 'Next century'], // 60*60*24*7*4*12*100*2
    [58060800000, 'centuries', 2903040000] // 60*60*24*7*4*12*100*20, 60*60*24*7*4*12*100
  ];
  var seconds = (+new Date() - time) / 1000,
    token = 'ago',
    list_choice = 1;

  if (seconds == 0) {
    return 'Just now'
  }
  if (seconds < 0) {
    seconds = Math.abs(seconds);
    token = 'from now';
    list_choice = 2;
  }
  var i = 0,
    format;
  while (format = time_formats[i++])
    if (seconds < format[0]) {
      if (typeof format[2] == 'string')
        return format[list_choice];
      else
        return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;
    }
  return time;
}

var aDay = 24 * 60 * 60 * 1000;
console.log(time_ago(new Date(Date.now() - aDay)));
console.log(time_ago(new Date(Date.now() - aDay * 2)));

【讨论】:

  • 将最后一行 return time; 替换为 format = time_formats[time_formats.length - 1]; return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token; 以返回大时间跨度的世纪而不是毫秒。
  • 非常好!虽然我在 iOS 中注意到,当使用 angular 作为过滤器时,浏览器会在此处返回 NaN。这修复了它: time = +new Date(time.replace(/-/g, '/'));
  • 很好,但是那个while循环中的赋值是丑陋和混乱的。改成 forEach 循环会更好
  • 我遇到了一个问题,我无法看到“刚刚”,并且在 0 秒前一直出现。所以我将线路改为if (seconds &lt; 1) { return 'Just now' },这解决了我的问题
【解决方案4】:

我没有检查过(虽然不难),但我认为 Stack Exchange 网站使用 jquery.timeago plugin 来创建这些时间字符串


这个插件使用起来非常简单,而且它很干净并且会自动更新。

这是一个快速示例(来自插件的主页):

首先,加载 jQuery 和插件:

<script src="jquery.min.js" type="text/javascript"></script> <script src="jquery.timeago.js" type="text/javascript"></script>

现在,让我们将它附加到您的 DOM 就绪的时间戳:

jQuery(document).ready(function() {
jQuery("abbr.timeago").timeago(); });

这将把所有abbr元素 具有timeago 的类和 ISO 标题中的 8601 时间戳:<abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr> 变成这样的: <abbr class="timeago" title="July 17, 2008">about a year ago</abbr>哪个 产量:大约一年前。随着时间的 通过,时间戳将 自动更新。

【讨论】:

  • 不是每个人都使用 JQuery。
  • 把它作为一个 jquery 插件是没有意义的。
【解决方案5】:

这是对 Sky Sander 解决方案的轻微修改,允许将日期作为字符串输入,并且能够显示像“1 分钟”而不是“73 秒”这样的跨度

var timeSince = function(date) {
  if (typeof date !== 'object') {
    date = new Date(date);
  }

  var seconds = Math.floor((new Date() - date) / 1000);
  var intervalType;

  var interval = Math.floor(seconds / 31536000);
  if (interval >= 1) {
    intervalType = 'year';
  } else {
    interval = Math.floor(seconds / 2592000);
    if (interval >= 1) {
      intervalType = 'month';
    } else {
      interval = Math.floor(seconds / 86400);
      if (interval >= 1) {
        intervalType = 'day';
      } else {
        interval = Math.floor(seconds / 3600);
        if (interval >= 1) {
          intervalType = "hour";
        } else {
          interval = Math.floor(seconds / 60);
          if (interval >= 1) {
            intervalType = "minute";
          } else {
            interval = seconds;
            intervalType = "second";
          }
        }
      }
    }
  }

  if (interval > 1 || interval === 0) {
    intervalType += 's';
  }

  return interval + ' ' + intervalType;
};
var aDay = 24 * 60 * 60 * 1000;
console.log(timeSince(new Date(Date.now() - aDay)));
console.log(timeSince(new Date(Date.now() - aDay * 2)));

【讨论】:

  • 这在几秒钟内不起作用,因为间隔从 interval = Math.floor(seconds / 60); 保留为 0。我将interval = seconds; 添加到最终的else 中,效果很好。
  • 如果interval为0,还要加上“s”。
  • 这太棒了。对于 TS,我必须在 let seconds = Math.floor((+new Date() - date) / 1000); 上添加一元运算符
  • 你为什么还要检查最后一个if中的interval === 0
  • @smartmouse 这样它就会说“0 秒”而不是“0 秒”
【解决方案6】:

Lokely 使用的较短版本:

const intervals = [
  { label: 'year', seconds: 31536000 },
  { label: 'month', seconds: 2592000 },
  { label: 'day', seconds: 86400 },
  { label: 'hour', seconds: 3600 },
  { label: 'minute', seconds: 60 },
  { label: 'second', seconds: 1 }
];

function timeSince(date) {
  const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
  const interval = intervals.find(i => i.seconds < seconds);
  const count = Math.floor(seconds / interval.seconds);
  return `${count} ${interval.label}${count !== 1 ? 's' : ''} ago`;
}

【讨论】:

  • 最短间隔的持续时间为零秒 - 这会导致除以零错误。
  • @apk 是对的。 Infinity seconds ago
【解决方案7】:

你可能想看看humanized_time_span:https://github.com/layam/js_humanized_time_span

它与框架无关且完全可定制。

只需下载/包含脚本,然后您就可以执行此操作:

humanized_time_span("2011-05-11 12:00:00")  
   => '3 hours ago'

humanized_time_span("2011-05-11 12:00:00", "2011-05-11 16:00:00)  
   => '4 hours ago'

甚至这个:

var custom_date_formats = {
  past: [
    { ceiling: 60, text: "less than a minute ago" },
    { ceiling: 86400, text: "$hours hours, $minutes minutes and $seconds seconds ago" },
    { ceiling: null, text: "$years years ago" }
  ],
  future: [
    { ceiling: 60, text: "in less than a minute" },
    { ceiling: 86400, text: "in $hours hours, $minutes minutes and $seconds seconds time" },
    { ceiling: null, text: "in $years years" }
  ]
}

humanized_time_span("2010/09/10 10:00:00", "2010/09/10 10:00:05", custom_date_formats) 
  => "less than a minute ago"

阅读文档了解更多信息。

【讨论】:

  • 只是表示它不依赖jQuery,甚至没有DOM。
  • 它给了我NaN years ago 为什么??
  • 该死,我明白了......你使用它的例子是错误的。你实际上用斜线而不是“-”来分隔第一个数字。像这样humanized_time_span("2011/05/11 12:00:00")
  • 这可能取决于您当地的文化并且因用户而异:)
【解决方案8】:

@user1012181 提供的 ES6 版本代码:

const epochs = [
    ['year', 31536000],
    ['month', 2592000],
    ['day', 86400],
    ['hour', 3600],
    ['minute', 60],
    ['second', 1]
];

const getDuration = (timeAgoInSeconds) => {
    for (let [name, seconds] of epochs) {
        const interval = Math.floor(timeAgoInSeconds / seconds);
        if (interval >= 1) {
            return {
                interval: interval,
                epoch: name
            };
        }
    }
};

const timeAgo = (date) => {
    const timeAgoInSeconds = Math.floor((new Date() - new Date(date)) / 1000);
    const {interval, epoch} = getDuration(timeAgoInSeconds);
    const suffix = interval === 1 ? '' : 's';
    return `${interval} ${epoch}${suffix} ago`;
};

根据@ibe-vanmeenen 的建议进行了编辑。 (谢谢!)

【讨论】:

  • 您还应该在 EPOCHS 中包含“second: 1”,否则如果不到 1 分钟就会中断 :)。最后 3 个 vars 也可以是一个常量 no?
  • 另外,EPOCHS 应该是一个数组,因为对象不保证属性顺序。我已将更改存储在 gist.github.com/IbeVanmeenen/4e3e58820c9168806e57530563612886 中。欢迎您复制它们以编辑此答案:)
【解决方案9】:

把上面的函数改成

function timeSince(date) {

    var seconds = Math.floor(((new Date().getTime()/1000) - date)),
    interval = Math.floor(seconds / 31536000);

    if (interval > 1) return interval + "y";

    interval = Math.floor(seconds / 2592000);
    if (interval > 1) return interval + "m";

    interval = Math.floor(seconds / 86400);
    if (interval >= 1) return interval + "d";

    interval = Math.floor(seconds / 3600);
    if (interval >= 1) return interval + "h";

    interval = Math.floor(seconds / 60);
    if (interval > 1) return interval + "m ";

    return Math.floor(seconds) + "s";
}

否则,它会显示“75 分钟”(1 到 2 小时之间)之类的内容。它现在还假设输入日期是 Unix 时间戳。

【讨论】:

  • 请将日期除以 1000。
  • 我在数据来自数据库的情况下使用了这个,Unix 时间戳以秒为单位。当它以毫秒为单位时,您确实需要除以 1000。
【解决方案10】:

可读性强且跨浏览器兼容的代码:

@Travis 给出的

var DURATION_IN_SECONDS = {
  epochs: ['year', 'month', 'day', 'hour', 'minute'],
  year: 31536000,
  month: 2592000,
  day: 86400,
  hour: 3600,
  minute: 60
};

function getDuration(seconds) {
  var epoch, interval;

  for (var i = 0; i < DURATION_IN_SECONDS.epochs.length; i++) {
    epoch = DURATION_IN_SECONDS.epochs[i];
    interval = Math.floor(seconds / DURATION_IN_SECONDS[epoch]);
    if (interval >= 1) {
      return {
        interval: interval,
        epoch: epoch
      };
    }
  }

};

function timeSince(date) {
  var seconds = Math.floor((new Date() - new Date(date)) / 1000);
  var duration = getDuration(seconds);
  var suffix = (duration.interval > 1 || duration.interval === 0) ? 's' : '';
  return duration.interval + ' ' + duration.epoch + suffix;
};

alert(timeSince('2015-09-17T18:53:23'));

【讨论】:

  • 请注意,这会产生一些错误的假设,例如每天是 86,400 秒(除非时区设置为 UTC,由于 UTC,这并不总是正确的)
【解决方案11】:

所以这是我的版本,它适用于过去和未来的日期。 它使用Intl.RelativeTimeFormat 提供本地化字符串,而不是硬编码字符串。 您可以将日期作为时间戳、日期对象或可解析的日期字符串传递。

/**
 * Human readable elapsed or remaining time (example: 3 minutes ago)
 * @param  {Date|Number|String} date A Date object, timestamp or string parsable with Date.parse()
 * @param  {Date|Number|String} [nowDate] A Date object, timestamp or string parsable with Date.parse()
 * @param  {Intl.RelativeTimeFormat} [trf] A Intl formater
 * @return {string} Human readable elapsed or remaining time
 * @author github.com/victornpb
 * @see https://stackoverflow.com/a/67338038/938822
 */
function fromNow(date, nowDate = Date.now(), rft = new Intl.RelativeTimeFormat(undefined, { numeric: "auto" })) {
    const SECOND = 1000;
    const MINUTE = 60 * SECOND;
    const HOUR = 60 * MINUTE;
    const DAY = 24 * HOUR;
    const WEEK = 7 * DAY;
    const MONTH = 30 * DAY;
    const YEAR = 365 * DAY;
    const intervals = [
        { ge: YEAR, divisor: YEAR, unit: 'year' },
        { ge: MONTH, divisor: MONTH, unit: 'month' },
        { ge: WEEK, divisor: WEEK, unit: 'week' },
        { ge: DAY, divisor: DAY, unit: 'day' },
        { ge: HOUR, divisor: HOUR, unit: 'hour' },
        { ge: MINUTE, divisor: MINUTE, unit: 'minute' },
        { ge: 30 * SECOND, divisor: SECOND, unit: 'seconds' },
        { ge: 0, divisor: 1, text: 'just now' },
    ];
    const now = typeof nowDate === 'object' ? nowDate.getTime() : new Date(nowDate).getTime();
    const diff = now - (typeof date === 'object' ? date : new Date(date)).getTime();
    const diffAbs = Math.abs(diff);
    for (const interval of intervals) {
        if (diffAbs >= interval.ge) {
            const x = Math.round(Math.abs(diff) / interval.divisor);
            const isFuture = diff < 0;
            return interval.unit ? rft.format(isFuture ? x : -x, interval.unit) : interval.text;
        }
    }
}
// examples
fromNow('2020-01-01') // 9 months ago
fromNow(161651684156) // 4 days ago
fromNow(new Date()-1) // just now
fromNow(30000 + Date.now()) // in 30 seconds
fromNow(Date.now() + (1000*60*60*24)) // in 1 day
fromNow(new Date('2029-12-01Z00:00:00.000')) // in 9 years

不使用 Intl.RelativeTimeFormat 的替代方案

/**
 * Human readable elapsed or remaining time (example: 3 minutes ago)
 * @param  {Date|Number|String} date A Date object, timestamp or string parsable with Date.parse()
 * @return {string} Human readable elapsed or remaining time
 * @author github.com/victornpb
 * @see https://stackoverflow.com/a/67338038/938822
 */
function fromNow(date) {
    const SECOND = 1000;
    const MINUTE = 60 * SECOND;
    const HOUR = 60 * MINUTE;
    const DAY = 24 * HOUR;
    const WEEK = 7 * DAY;
    const MONTH = 30 * DAY;
    const YEAR = 365 * DAY;
    const units = [
        { max: 30 * SECOND, divisor: 1, past1: 'just now', pastN: 'just now', future1: 'just now', futureN: 'just now' },
        { max: MINUTE, divisor: SECOND, past1: 'a second ago', pastN: '# seconds ago', future1: 'in a second', futureN: 'in # seconds' },
        { max: HOUR, divisor: MINUTE, past1: 'a minute ago', pastN: '# minutes ago', future1: 'in a minute', futureN: 'in # minutes' },
        { max: DAY, divisor: HOUR, past1: 'an hour ago', pastN: '# hours ago', future1: 'in an hour', futureN: 'in # hours' },
        { max: WEEK, divisor: DAY, past1: 'yesterday', pastN: '# days ago', future1: 'tomorrow', futureN: 'in # days' },
        { max: 4 * WEEK, divisor: WEEK, past1: 'last week', pastN: '# weeks ago', future1: 'in a week', futureN: 'in # weeks' },
        { max: YEAR, divisor: MONTH, past1: 'last month', pastN: '# months ago', future1: 'in a month', futureN: 'in # months' },
        { max: 100 * YEAR, divisor: YEAR, past1: 'last year', pastN: '# years ago', future1: 'in a year', futureN: 'in # years' },
        { max: 1000 * YEAR, divisor: 100 * YEAR, past1: 'last century', pastN: '# centuries ago', future1: 'in a century', futureN: 'in # centuries' },
        { max: Infinity, divisor: 1000 * YEAR, past1: 'last millennium', pastN: '# millennia ago', future1: 'in a millennium', futureN: 'in # millennia' },
    ];
    const diff = Date.now() - (typeof date === 'object' ? date : new Date(date)).getTime();
    const diffAbs = Math.abs(diff);
    for (const unit of units) {
        if (diffAbs < unit.max) {
            const isFuture = diff < 0;
            const x = Math.round(Math.abs(diff) / unit.divisor);
            if (x <= 1) return isFuture ? unit.future1 : unit.past1;
            return (isFuture ? unit.futureN : unit.pastN).replace('#', x);
        }
    }
};

【讨论】:

  • 您的版本有几个验证错误。在typescriptlang.org/play 中尝试验证它。
  • @jwillmer wdym?这不是打字稿。没有任何验证。
  • 我只是想在做了这么多工作之后你想让它通过 ESLint ;)
【解决方案12】:

从现在开始,unix 时间戳参数,

function timeSince(ts){
    now = new Date();
    ts = new Date(ts*1000);
    var delta = now.getTime() - ts.getTime();

    delta = delta/1000; //us to s

    var ps, pm, ph, pd, min, hou, sec, days;

    if(delta<=59){
        ps = (delta>1) ? "s": "";
        return delta+" second"+ps
    }

    if(delta>=60 && delta<=3599){
        min = Math.floor(delta/60);
        sec = delta-(min*60);
        pm = (min>1) ? "s": "";
        ps = (sec>1) ? "s": "";
        return min+" minute"+pm+" "+sec+" second"+ps;
    }

    if(delta>=3600 && delta<=86399){
        hou = Math.floor(delta/3600);
        min = Math.floor((delta-(hou*3600))/60);
        ph = (hou>1) ? "s": "";
        pm = (min>1) ? "s": "";
        return hou+" hour"+ph+" "+min+" minute"+pm;
    } 

    if(delta>=86400){
        days = Math.floor(delta/86400);
        hou =  Math.floor((delta-(days*86400))/60/60);
        pd = (days>1) ? "s": "";
        ph = (hou>1) ? "s": "";
        return days+" day"+pd+" "+hou+" hour"+ph;
    }

}

【讨论】:

    【解决方案13】:

    这应该正确处理任何有效的时间戳,包括 Date.now()、单数单位和未来日期。我遗漏了几个月,但这些应该很容易添加。我尽量保持它的可读性。

    function getTimeInterval(date) {
      let seconds = Math.floor((Date.now() - date) / 1000);
      let unit = "second";
      let direction = "ago";
      if (seconds < 0) {
        seconds = -seconds;
        direction = "from now";
      }
      let value = seconds;
      if (seconds >= 31536000) {
        value = Math.floor(seconds / 31536000);
        unit = "year";
      } else if (seconds >= 86400) {
        value = Math.floor(seconds / 86400);
        unit = "day";
      } else if (seconds >= 3600) {
        value = Math.floor(seconds / 3600);
        unit = "hour";
      } else if (seconds >= 60) {
        value = Math.floor(seconds / 60);
        unit = "minute";
      }
      if (value != 1)
        unit = unit + "s";
      return value + " " + unit + " " + direction;
    }
    
    console.log(getTimeInterval(Date.now())); // 0 seconds ago
    console.log(getTimeInterval(Date.now() + 1000)); // 1 second from now
    console.log(getTimeInterval(Date.now() - 1000)); // 1 second ago
    console.log(getTimeInterval(Date.now() + 60000)); // 1 minute from now
    console.log(getTimeInterval(Date.now() - 120000)); // 2 minutes ago
    console.log(getTimeInterval(Date.now() + 120000)); // 2 minutes from now
    console.log(getTimeInterval(Date.now() + 3600000)); // 1 hour from now
    console.log(getTimeInterval(Date.now() + 360000000000)); // 11 years from now
    console.log(getTimeInterval(0)); // 49 years ago

    【讨论】:

      【解决方案14】:

      虽然这个问题是很久以前提出的,但写下这个答案希望它会对某人有所帮助。

      传递您想要开始计数的日期。使用 momentjsmoment().fromNow():(查看更多信息here

      getRelativeTime(date) {
          const d = new Date(date * 1000);
          return moment(d).fromNow();
      }
      

      如果您想更改为从现在提供的日期提供的信息,您可以写下您的自定义相对时间。

      例如,在我自己的情况下,我想打印 'one month ago' 而不是 'a month ago'由 moment(d).fromNow() 提供)。在这种情况下,您可以编写下面给出的内容。

      moment.updateLocale('en', {
          relativeTime: {
              future: 'in %s',
              past: '%s ago',
              s: 'a few seconds',
              ss: '%d seconds',
              m: '1 m',
              mm: '%d minutes',
              h: '1 h',
              hh: '%d hours',
              d: '1 d',
              dd: '%d days',
              M: '1 month',
              MM: '%d months',
              y: '1 y',
              yy: '%d years'
          }
      });
      

      注意:我在 Angular 6

      中编写了我的项目代码

      【讨论】:

      • 完美运行。谢谢!
      • @Nima,如果有帮助,我很高兴 :))
      【解决方案15】:

      简单易读的版本:

      const NOW = new Date()
      const times = [["second", 1], ["minute", 60], ["hour", 3600], ["day", 86400], ["week", 604800], ["month", 2592000], ["year", 31536000]]
      
      function timeAgo(date) {
          var diff = Math.round((NOW - date) / 1000)
          for (var t = 0; t < times.length; t++) {
              if (diff < times[t][1]) {
                  if (t == 0) {
                      return "Just now"
                  } else {
                      diff = Math.round(diff / times[t - 1][1])
                      return diff + " " + times[t - 1][0] + (diff == 1?" ago":"s ago")
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案16】:

        也可以使用dayjsrelativeTime插件解决这个问题。

        import * as dayjs from 'dayjs';
        import * as relativeTime from 'dayjs/plugin/relativeTime';
        
        dayjs.extend(relativeTime);
        dayjs(dayjs('1990')).fromNow(); // x years ago
        

        【讨论】:

          【解决方案17】:

          Intl.RelativeTimeFormat的另一种看法

          • 支持过去和未来的日期
          • 接受StringDate
          • 自定义范围很容易添加(编辑ranges
          • 可以轻松翻译Intl.RelativeTimeFormat('ua')

          console.log(timeAgo('2021-08-09T15:29:01+0000'));
          
          function timeAgo(input) {
            const date = (input instanceof Date) ? input : new Date(input);
            const formatter = new Intl.RelativeTimeFormat('en');
            const ranges = {
              years: 3600 * 24 * 365,
              months: 3600 * 24 * 30,
              weeks: 3600 * 24 * 7,
              days: 3600 * 24,
              hours: 3600,
              minutes: 60,
              seconds: 1
            };
            const secondsElapsed = (date.getTime() - Date.now()) / 1000;
            for (let key in ranges) {
              if (ranges[key] < Math.abs(secondsElapsed)) {
                const delta = secondsElapsed / ranges[key];
                return formatter.format(Math.round(delta), key);
              }
            }
          }

          https://jsfiddle.net/tv9701uf

          【讨论】:

            【解决方案18】:

            我用js和python写了一个,用在两个项目中,很好很简单:a simple library (less then 2kb) used to format date with *** time ago statement.

            简单、小巧、易于使用且经过良好测试。

            1. npm install timeago.js

            2. import timeago from 'timeago.js'; // or use script tag

            3. 使用apiformat

            示例:

            var timeagoIns  = timeago();
            timeagoIns .format('2016-06-12');
            

            您还可以实时渲染。

            var timeagoIns = timeago();
            timeagoIns.render(document.querySelectorAll('time'));
            

            【讨论】:

            • 从 4.0 开始,您可以改用解构导入:import { format, render, cancel, register } from 'timeago.js';
            【解决方案19】:
            function dateToHowManyAgo(stringDate){
                var currDate = new Date();
                var diffMs=currDate.getTime() - new Date(stringDate).getTime();
                var sec=diffMs/1000;
                if(sec<60)
                    return parseInt(sec)+' second'+(parseInt(sec)>1?'s':'')+' ago';
                var min=sec/60;
                if(min<60)
                    return parseInt(min)+' minute'+(parseInt(min)>1?'s':'')+' ago';
                var h=min/60;
                if(h<24)
                    return parseInt(h)+' hour'+(parseInt(h)>1?'s':'')+' ago';
                var d=h/24;
                if(d<30)
                    return parseInt(d)+' day'+(parseInt(d)>1?'s':'')+' ago';
                var m=d/30;
                if(m<12)
                    return parseInt(m)+' month'+(parseInt(m)>1?'s':'')+' ago';
                var y=m/12;
                return parseInt(y)+' year'+(parseInt(y)>1?'s':'')+' ago';
            }
            console.log(dateToHowManyAgo('2019-11-07 19:17:06'));
            

            【讨论】:

              【解决方案20】:

              我修改了 Sky Sanders 的版本。 Math.floor(...) 操作在 if 块中进行评估

                     var timeSince = function(date) {
                          var seconds = Math.floor((new Date() - date) / 1000);
                          var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
                          if (seconds < 5){
                              return "just now";
                          }else if (seconds < 60){
                              return seconds + " seconds ago";
                          }
                          else if (seconds < 3600) {
                              minutes = Math.floor(seconds/60)
                              if(minutes > 1)
                                  return minutes + " minutes ago";
                              else
                                  return "1 minute ago";
                          }
                          else if (seconds < 86400) {
                              hours = Math.floor(seconds/3600)
                              if(hours > 1)
                                  return hours + " hours ago";
                              else
                                  return "1 hour ago";
                          }
                          //2 days and no more
                          else if (seconds < 172800) {
                              days = Math.floor(seconds/86400)
                              if(days > 1)
                                  return days + " days ago";
                              else
                                  return "1 day ago";
                          }
                          else{
              
                              //return new Date(time).toLocaleDateString();
                              return date.getDate().toString() + " " + months[date.getMonth()] + ", " + date.getFullYear();
                          }
                      }
              

              【讨论】:

              • 如果return days + "1 day ago"; 应该是return "1 day ago";,则最后一个else 中有错字
              【解决方案21】:

              回答10年前的问题以帮助新人。

              我们可以将这个包用于那个javascript-time-ago

               
              // Load locale-specific relative date/time formatting rules.
              import en from 'javascript-time-ago/locale/en'
               
              // Add locale-specific relative date/time formatting rules.
              TimeAgo.addLocale(en)
               
              // Create relative date/time formatter.
              const timeAgo = new TimeAgo('en-US')
               
              timeAgo.format(new Date())
              // "just now"
               
              timeAgo.format(Date.now() - 60 * 1000)
              // "a minute ago"
               
              timeAgo.format(Date.now() - 2 * 60 * 60 * 1000)
              // "2 hours ago"
               
              timeAgo.format(Date.now() - 24 * 60 * 60 * 1000)
              // "a day ago"
              

              【讨论】:

                【解决方案22】:

                我根据其他答案对此进行了尝试。

                function timeSince(date) {
                    let minute = 60;
                    let hour   = minute * 60;
                    let day    = hour   * 24;
                    let month  = day    * 30;
                    let year   = day    * 365;
                
                    let suffix = ' ago';
                
                    let elapsed = Math.floor((Date.now() - date) / 1000);
                
                    if (elapsed < minute) {
                        return 'just now';
                    }
                
                    // get an array in the form of [number, string]
                    let a = elapsed < hour  && [Math.floor(elapsed / minute), 'minute'] ||
                            elapsed < day   && [Math.floor(elapsed / hour), 'hour']     ||
                            elapsed < month && [Math.floor(elapsed / day), 'day']       ||
                            elapsed < year  && [Math.floor(elapsed / month), 'month']   ||
                            [Math.floor(elapsed / year), 'year'];
                
                    // pluralise and append suffix
                    return a[0] + ' ' + a[1] + (a[0] === 1 ? '' : 's') + suffix;
                }
                

                【讨论】:

                  【解决方案23】:
                  const createdAt = moment(created_at).fromNow()
                  

                  以及定制的解决方案

                  
                          const duration = moment.duration(moment().diff(moment(created_at)))
                          const createdAt = duration.as('week') >= 1
                            ? `${Math.floor(duration.as('week'))} week(s)`
                            : duration.as('day') >= 1
                              ? `${Math.floor(duration.as('day'))} day(s)`
                              : duration.as('hour') >= 1
                                ? `${Math.floor(duration.as('hour'))} hour(s)`
                                : `${Math.floor(duration.as('minute'))} minute(s)`
                  
                  

                  【讨论】:

                    【解决方案24】:
                    function timeago(date) {
                        var seconds = Math.floor((new Date() - date) / 1000);
                        if(Math.round(seconds/(60*60*24*365.25)) >= 2) return Math.round(seconds/(60*60*24*365.25)) + " years ago";
                        else if(Math.round(seconds/(60*60*24*365.25)) >= 1) return "1 year ago";
                        else if(Math.round(seconds/(60*60*24*30.4)) >= 2) return Math.round(seconds/(60*60*24*30.4)) + " months ago";
                        else if(Math.round(seconds/(60*60*24*30.4)) >= 1) return "1 month ago";
                        else if(Math.round(seconds/(60*60*24*7)) >= 2) return Math.round(seconds/(60*60*24*7)) + " weeks ago";
                        else if(Math.round(seconds/(60*60*24*7)) >= 1) return "1 week ago";
                        else if(Math.round(seconds/(60*60*24)) >= 2) return Math.round(seconds/(60*60*24)) + " days ago";
                        else if(Math.round(seconds/(60*60*24)) >= 1) return "1 day ago";
                        else if(Math.round(seconds/(60*60)) >= 2) return Math.round(seconds/(60*60)) + " hours ago";
                        else if(Math.round(seconds/(60*60)) >= 1) return "1 hour ago";
                        else if(Math.round(seconds/60) >= 2) return Math.round(seconds/60) + " minutes ago";
                        else if(Math.round(seconds/60) >= 1) return "1 minute ago";
                        else if(seconds >= 2)return seconds + " seconds ago";
                        else return seconds + "1 second ago";
                    }
                    

                    【讨论】:

                      【解决方案25】:

                      我的解决方案..

                      (function(global){
                                  const SECOND   = 1;
                                  const MINUTE   = 60;
                                  const HOUR     = 3600;
                                  const DAY      = 86400;
                                  const MONTH    = 2629746;
                                  const YEAR     = 31556952;
                                  const DECADE   = 315569520;
                      
                                  global.timeAgo = function(date){
                                      var now = new Date();
                                      var diff = Math.round(( now - date ) / 1000);
                      
                                      var unit = '';
                                      var num = 0;
                                      var plural = false;
                      
                                      switch(true){
                                          case diff <= 0:
                                              return 'just now';
                                          break;
                      
                                          case diff < MINUTE:
                                              num = Math.round(diff / SECOND);
                                              unit = 'sec';
                                              plural = num > 1;
                                          break;
                      
                                          case diff < HOUR:
                                              num = Math.round(diff / MINUTE);
                                              unit = 'min';
                                              plural = num > 1;
                                          break;
                      
                                          case diff < DAY:
                                              num = Math.round(diff / HOUR);
                                              unit = 'hour';
                                              plural = num > 1;
                                          break;
                      
                                          case diff < MONTH:
                                              num = Math.round(diff / DAY);
                                              unit = 'day';
                                              plural = num > 1;
                                          break;
                      
                                          case diff < YEAR:
                                              num = Math.round(diff / MONTH);
                                              unit = 'month';
                                              plural = num > 1;
                                          break;
                      
                                          case diff < DECADE:
                                              num = Math.round(diff / YEAR);
                                              unit = 'year';
                                              plural = num > 1;
                                          break;
                      
                                          default:
                                              num = Math.round(diff / YEAR);
                                              unit = 'year';
                                              plural = num > 1;
                                      }
                      
                                      var str = '';
                                      if(num){
                                          str += `${num} `;
                                      }
                      
                                      str += `${unit}`;
                      
                                      if(plural){
                                          str += 's';
                                      }
                      
                                      str += ' ago';
                      
                                      return str;
                                  }
                              })(window);
                      
                              console.log(timeAgo(new Date()));
                              console.log(timeAgo(new Date('Jun 03 2018 15:12:19 GMT+0300 (FLE Daylight Time)')));
                              console.log(timeAgo(new Date('Jun 03 2018 13:12:19 GMT+0300 (FLE Daylight Time)')));
                              console.log(timeAgo(new Date('May 28 2018 13:12:19 GMT+0300 (FLE Daylight Time)')));
                              console.log(timeAgo(new Date('May 28 2017 13:12:19 GMT+0300 (FLE Daylight Time)')));
                              console.log(timeAgo(new Date('May 28 2000 13:12:19 GMT+0300 (FLE Daylight Time)')));
                              console.log(timeAgo(new Date('Sep 10 1994 13:12:19 GMT+0300 (FLE Daylight Time)')));
                      

                      【讨论】:

                        【解决方案26】:

                        我一直在寻找这个问题的答案并几乎实现了其中一个解决方案,但一位同事提醒我检查react-intl 库,因为我们已经在使用它了。

                        所以添加到解决方案...如果您使用 react-intl 库,他们有一个 &lt;FormattedRelative&gt; 组件。

                        https://github.com/yahoo/react-intl/wiki/Components#formattedrelative

                        【讨论】:

                          【解决方案27】:

                          这是我所做的(对象返回时间单位及其值):

                          function timeSince(post_date, reference)
                          {
                          	var reference = reference ? new Date(reference) : new Date(),
                          		diff = reference - new Date(post_date + ' GMT-0000'),
                          		date = new Date(diff),
                          		object = { unit: null, value: null };
                          	
                          	if (diff < 86400000)
                          	{
                          		var secs  = date.getSeconds(),
                          			mins  = date.getMinutes(),
                          			hours = date.getHours(),
                          			array = [ ['second', secs], ['minute', mins], ['hour', hours] ];
                          	}
                          	else
                          	{
                          		var days   = date.getDate(),
                          			weeks  = Math.floor(days / 7),
                          			months = date.getMonth(),
                          			years  = date.getFullYear() - 1970,
                          			array  = [ ['day', days], ['week', weeks], ['month', months], ['year', years] ];
                          	}
                          
                          	for (var i = 0; i < array.length; i++)
                          	{
                          		array[i][0] += array[i][1] != 1 ? 's' : '';
                          
                          		object.unit  = array[i][1] >= 1 ? array[i][0] : object.unit;
                          		object.value = array[i][1] >= 1 ? array[i][1] : object.value;
                          	}
                          
                          	return object;
                          }

                          【讨论】:

                            【解决方案28】:
                             I achieve this by following method
                            
                               timeAgo = (date) => {
                                        var ms = (new Date()).getTime() - date.getTime();
                                        var seconds = Math.floor(ms / 1000);
                                        var minutes = Math.floor(seconds / 60);
                                    var hours = Math.floor(minutes / 60);
                                    var days = Math.floor(hours / 24);
                                    var months = Math.floor(days / 30);
                                    var years = Math.floor(months / 12);
                                
                                    if (ms === 0) {
                                        return 'Just now';
                                    } if (seconds < 60) {
                                        return seconds + ' seconds Ago';
                                    } if (minutes < 60) {
                                        return minutes + ' minutes Ago';
                                    } if (hours < 24) {
                                        return hours + ' hours Ago';
                                    } if (days < 30) {
                                        return days + ' days Ago';
                                    } if (months < 12) {
                                        return months + ' months Ago';
                                    } else {
                                        return years + ' years Ago';
                                    }
                                
                                }
                                
                                    console.log(timeAgo(new Date()));
                                    console.log(timeAgo(new Date('Jun 27 2020 10:12:19')));
                                    console.log(timeAgo(new Date('Jun 27 2020 00:12:19')));
                                    console.log(timeAgo(new Date('May 28 2020 13:12:19')));
                                    console.log(timeAgo(new Date('May 28 2017 13:12:19')));
                            

                            【讨论】:

                            • 这对任何现有答案有何改进,包括 十年前的 Sky Sanders?
                            【解决方案29】:

                            这是@sky-sanders 答案的简化版本。

                            function timeSince(date) {
                            
                              var seconds = Math.floor((new Date() - date) / 1000);
                              var divisors = [31536000, 2592000, 86400, 3600, 60, 1]
                              var description = ["years", "months", "days", "hours", "minutes", "seconds"]
                              var result = [];
                            
                              var interval = seconds;
                            
                              for (i = 0; i < divisors.length; i++) {
                                interval = Math.floor(seconds / divisors[i])
                                if (interval > 1) {
                                  result.push(interval + " " + description[i])
                                }
                                seconds -= interval * divisors[i]
                              }
                            
                              return result.join(" ")
                            }
                            

                            【讨论】:

                              【解决方案30】:
                              function calDateAgo(dString=null){
                                  //var dString = "2021-04-1 12:00:00";
                                   
                                  var d1 = new Date(dString);
                                  var d2 = new Date();
                                  var t2 = d2.getTime();
                                  var t1 = d1.getTime();
                                  var d1Y = d1.getFullYear();
                                  var d2Y = d2.getFullYear();
                                  var d1M = d1.getMonth();
                                  var d2M = d2.getMonth();
                                   
                                  var time_obj = {};
                                  time_obj.year = d2.getFullYear()-d1.getFullYear();
                                  time_obj.month = (d2M+12*d2Y)-(d1M+12*d1Y);
                                  time_obj.week = parseInt((t2-t1)/(24*3600*1000*7));
                                  time_obj.day = parseInt((t2-t1)/(24*3600*1000));
                                  time_obj.hour = parseInt((t2-t1)/(3600*1000));
                                  time_obj.minute = parseInt((t2-t1)/(60*1000));
                                  time_obj.second = parseInt((t2-t1)/(1000));
                              
                                  for (const obj_key in time_obj) {
                                      if(time_obj[obj_key] == 0){
                                          delete time_obj[obj_key];
                                      }
                                  }
                                  var ago_text = 'just now';
                              
                                  if(typeof Object.keys(time_obj)[0] != 'undefined'){
                                      var time_key = Object.keys(time_obj)[0];
                                      var time_val = time_obj[Object.keys(time_obj)[0]];
                                      time_key += (time_val > 1) ? 's':'';
                                      ago_text = time_val+' '+time_key+' ago'; 
                                  }
                                  
                                  return ago_text;
                              }
                              

                              【讨论】:

                                猜你喜欢
                                • 2012-05-18
                                • 2011-03-11
                                • 1970-01-01
                                • 2020-08-27
                                • 1970-01-01
                                相关资源
                                最近更新 更多