如何格式化自 xxx 以来的时间,例如“4 分钟前”,类似于 Stack Exchange 站点

IT技术 javascript date-formatting
2021-01-16 11:41:51

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

例如

  • 1 分钟前
  • 1小时前
  • 1天前
  • 1个月前
  • 1年前
6个回答

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 - 是的,单点出口在不碍事的情况下有它的优点。现在那些把它看得太重的人误解了格言的起源。
2021-03-17 11:41:51
永远不要使用字符串连接,如果你想要一个可以国际化的解决方案,可以使用 String.format
2021-03-23 11:41:51
功能不错,但有些评论。将第一行更改为: var seconds = Math.floor(((new Date().getTime()/1000) - date)) 以使用 unix 时间戳。并且需要将 intval > 1 更改为 intval >=1 否则它会显示 75 分钟(1 到 2 小时之间)之类的内容。
2021-03-28 11:41:51
如果我想把它放在 div 类中怎么办?我能做什么?抱歉,我不是 javascript 专家。我试过这个 document.getElementsByTagName('.sampleclass')[0].innerHTML = timeSince(date); 和这个 document.getElementById('idname')[0].innerHTML = timeSince(date); 但它不起作用。有什么帮助吗?谢谢你。
2021-03-28 11:41:51
@PanMan 如果您只是将 > 更改为 >= 那么您最终会得到“1 分钟”这样的时间。我发布了这个答案的修改版本,有条件地添加了“s”:stackoverflow.com/a/23259289/373655
2021-04-10 11:41:51

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

Moment.js 是一个 javascript 日期时间库,要将它用于这种情况,您需要执行以下操作:

moment(yourdate).fromNow()

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

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

您好,我正在使用您的答案来获取时差。如果我只需要类似日期的年份的第一个字母作为 y、月和 m 以及日作为 d,我该怎么办?
2021-04-08 11:41:51
我如何只获得 DM sh 而不是几天前几个月前使用它?
2021-04-09 11:41:51

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

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)));

非常好!虽然我在 iOS 中注意到,当使用 angular 作为过滤器时,浏览器会在此处返回 NaN。这修复了它: time = +new Date(time.replace(/-/g, '/'));
2021-03-11 11:41:51
我遇到了一个问题,我无法看到“刚才”,并且在 0 秒前一直显示。所以我改变了if (seconds < 1) { return 'Just now' }解决我的问题的行
2021-03-14 11:41:51
太好了,但是那个 while 循环中的分配既丑陋又令人困惑。改为 forEach 循环会更好
2021-03-26 11:41:51
替换最后一行return time;format = time_formats[time_formats.length - 1]; return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;以回报世纪以来,大的时间跨度内,而不是毫秒。
2021-04-08 11:41:51

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


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

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

首先,加载 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 插件是没有意义的。
2021-03-25 11:41:51
不是每个人都使用 JQuery。
2021-03-29 11:41:51

这是对 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 === 0最后if
2021-03-15 11:41:51
如果间隔为 0,则还应添加“s”。
2021-03-23 11:41:51
@smartmouse 这样它就会说“0 秒”而不是“0 秒”
2021-03-26 11:41:51
这太棒了。对于 TS,我必须添加一个一元运算符let seconds = Math.floor((+new Date() - date) / 1000);
2021-03-28 11:41:51
这在几秒钟内不起作用,因为间隔从 0 开始interval = Math.floor(seconds / 60);我添加interval = seconds;到决赛中else,效果很好。
2021-04-08 11:41:51