如何格式化时间自xxx例如“4分钟前”类似于堆栈交换网站

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

如。

  • 1分钟前
  • 1小时前
  • 1天前
  • 1个月前
  • 一年前
277975 次浏览

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

你可能想看看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"

更多信息请阅读文档。

将上面的函数更改为

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时间戳。

这将显示你过去和以前的时间格式,如“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)));

从现在开始,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;
}


}

在这种情况下可能是多余的,但如果机会显示moment.js是非常棒的!

js是一个javascript datetime库,在这种情况下使用它,你需要做:

moment(yourdate).fromNow()

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

2018附录: 勒克桑是一个新的现代库,可能值得一看!

2022附录: Day.js是一个较新的库,比Luxon轻80%,具有类似的功能。

以下是对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)));

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

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

由@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编辑建议。(谢谢!)

我修改了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();
}
}

我用js和python写了一个,在两个项目中使用,非常漂亮和简单:一个简单的库(小于2kb),用于用*** time ago语句格式化日期。

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

  1. npm install timeago.js

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

  3. 使用api format

示例:

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

你也可以实时渲染。

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

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

所以在解决方案中…在使用react-intl库的情况下,它们有一个<FormattedRelative>组件。

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

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

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

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";
}

死胡同使用的更短的版本:

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`;
}

我的解决方案。

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

虽然这个问题是很久以前问过的,但写下这个答案希望它能帮助到一些人。

传递您想要开始计数的日期。使用momentjsmoment().fromNow():(参见在这里的更多信息)

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

如果您想更改日期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'
}
});

请注意:我在角6中为项目编写了代码

简单易读版本:

const relativeTimePeriods = [
[31536000, 'year'],
[2419200, 'month'],
[604800, 'week'],
[86400, 'day'],
[3600, 'hour'],
[60, 'minute'],
[1, 'second']
];


function relativeTime(date, isUtc=true) {
if (!(date instanceof Date)) date = new Date(date * 1000);
const seconds = (new Date() - date) / 1000;
for (let [secondsPer, name] of relativeTimePeriods) {
if (seconds >= secondsPer) {
const amount = Math.floor(seconds / secondsPer);
return `${amount} ${name}${amount ? 's' : ''}s ago`;
}
}
return 'Just now';
}

也可以使用dayjs relativeTime插件来解决这个问题。

import * as dayjs from 'dayjs';
import * as relativeTime from 'dayjs/plugin/relativeTime';


dayjs.extend(relativeTime);
dayjs(dayjs('1990')).fromNow(); // x years ago

我的尝试是基于其他的答案。

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

这应该正确地处理任何有效的时间戳,包括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

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

回答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"

这是一个简化版的@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(" ")
}
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;
}

这是我的版本,它既适用于过去的日期,也适用于未来的日期。 它使用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);
}
}
};

另一个关于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

function mdiv(dividend, divisor) {
return [ Math.floor(dividend/divisor), dividend % divisor ];
}
// pass in milliseconds, gained by Date1.getTime() - Date2.getTime()
// if max_units is two, the result will be, for example
// 2years 12months ago, or 2hours 38minutes ago
// return formated period


function readable_period(ms, max_units=2){
let [yy, yr] = mdiv(ms, 3.154e10);
let [mm, mr] = mdiv(yr, 2.628e9);
let [dd, dr] = mdiv(mr, 8.64e7);
let [hh, hr] = mdiv(dr, 3.6e6);
let [tt, ss] = mdiv(hr, 6e4);


var ymdht = ['year', 'month', 'day', 'hour', 'minute'];
let res = [];
[yy, mm, dd, hh, tt].forEach((tis, ii)=>{
if(res.length === max_units){return};
if(tis !== 0){
res.push(tis === 1 ? `${tis}${ymdht[ii]}` : `${tis}${ymdht[ii]}s`);
}
});
return res.length === 0 ? '' : res.join(' ') + ' ago';
}
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)`


你可以使用勒克桑:

DateTime.toRelative()

https://moment.github.io/luxon/api-docs/index.html#datetimetorelative

这里还有一些例子:

const DateTime = luxon.DateTime;


// toRelative
console.log(DateTime.now().minus({ seconds: 1 }).toRelative()) // 1 second ago
console.log(DateTime.now().minus({ seconds: 10 }).toRelative()) // 10 seconds ago
console.log(DateTime.now().minus({ days: 2 }).toRelative())
console.log(DateTime.now().minus({ years: 3 }).toRelative())
console.log(DateTime.now().plus({ years: 3 }).toRelative())
console.log(DateTime.now().plus({ days: 2 }).toRelative())
console.log(DateTime.now().plus({ seconds: 1 }).toRelative())
console.log(DateTime.now().plus({ seconds: 10 }).toRelative())


// toRelativeCalendar
console.log(DateTime.now().minus({ seconds: 1 }).toRelativeCalendar()) // today
console.log(DateTime.now().minus({ seconds: 10 }).toRelativeCalendar()) // today
console.log(DateTime.now().minus({ days: 2 }).toRelativeCalendar())
console.log(DateTime.now().minus({ years: 3 }).toRelativeCalendar())
console.log(DateTime.now().plus({ years: 3 }).toRelativeCalendar())
console.log(DateTime.now().plus({ days: 2 }).toRelativeCalendar())
console.log(DateTime.now().plus({ seconds: 1 }).toRelativeCalendar())
console.log(DateTime.now().plus({ seconds: 10 }).toRelativeCalendar())
<script src="https://moment.github.io/luxon/global/luxon.min.js"></script>

我使用这个包:javascript-time-ago

  • < p > TimeAgo设置

     import TimeAgo from 'javascript-time-ago'
    import en from 'javascript-time-ago/locale/en.json'
    
    
    TimeAgo.addDefaultLocale(en)
    
  • 写一个函数 // twitter-now是twitter风格。查看docs中的更多选项

    const clockToDateString = (timestamp) =>
    timeAgo.format(new Date(timestamp.toNumber() * 1000), 'twitter-now')
    
  • 在dom中使用它

       <div >
    {clockToDateString(post.postTime)}
    </div>
    

使用这个,只是字面上复制所有的代码&只需将它导入到你的组件或任何地方&只要把你的ISOstring()日期放在里面:showTimeAgo("2022-06-20T13:42:29-05:00") &您将获得每个场景的自动时间更新。

旁注:我为这个https://www.npmjs.com/package/showtimeago做了一个npm包

export const showTimeAgo = () => {
const MONTH_NAMES = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];


function getOrdinalNum() {
return (
n +
(n > 0
? ['th', 'st', 'nd', 'rd'][
(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10
]
: '')
);
}


function getFormattedDate(
date,
preformattedDate = false,
hideYear = false
) {
const day = date.getDate();
const month = MONTH_NAMES[date.getMonth()];
const year = date.getFullYear();
let hours = date.getHours();
let minutes = date.getMinutes();


let ampm = hours >= 12 ? 'pm' : 'am';


switch(true){
case (hours > 12):
hours = hours - 12;
break;
case (hours === 0):
hours = 12;
break;
case(minutes < 10):
minutes = `0${minutes}`;
break;
case(preformattedDate):
// Today at 10:20am
// Yesterday at 10:20am
return `${preformattedDate} at ${hours}:${minutes} ${ampm}`;


case(hideYear):
// January 10th at 10:20pm
return `${month} ${getOrdinalNum(
day
)}, at ${hours}:${minutes} ${ampm}`;
default:
// January 10th 2022 at 10:20pm
return `${month} ${getOrdinalNum(
day
)}, ${year} at ${hours}:${minutes} ${ampm}`;
}
        

}


// --- Main function
function timeAgo(dateParam) {
if (!dateParam) {
return null;
}


const date =
typeof dateParam === 'object' ? dateParam : new Date(dateParam);
const DAY_IN_MS = 86400000; // 24 * 60 * 60 * 1000
const today = new Date();


const yesterday = new Date(today - DAY_IN_MS);


const seconds = Math.round((today - date) / 1000);
const minutes = Math.round(seconds / 60);
const hour = Math.round(seconds / 3600);
const day = Math.round(seconds / 86400);
const month = Math.round(seconds / 2629800);
const year = Math.floor(seconds / 31536000);
const isToday = today.toDateString() === date.toDateString();
const isYesterday =
yesterday.toDateString() === date.toDateString();
const isThisYear = today.getFullYear() === date.getFullYear();


switch(true){
case (seconds < 5):
return 'now';
case (seconds < 60):
return `${seconds} seconds ago`;
case (seconds < 90):
return 'about a minute ago';
case (minutes < 60):
return `${minutes} minutes ago`;
case (hour === 1 && hour < 2):
return `${hour} hour ago`; // 1 hour ago
case (hour > 1 && hour <= 12):
return `${hour} hours ago`; // 2 hours ago
case (isToday):
return getFormattedDate(date, 'Today'); // Today at 10:20am
case (isYesterday):
return getFormattedDate(date, 'Yesterday'); // Yesterday at 10:20am
case(day > 1 && day <= 30):
return `${day} days ago`; // 2 days ago
case (isThisYear):
return getFormattedDate(date, false, true); // January 10th at 10:20pm
case (day > 30 && month <= 1):
return `${hour} month ago`; // 1 month ago
case (month > 1 && month <= 12):
return `${month} months ago`; // 2 months ago
case (year === 1):
return `${year} year ago`; // 1 year ago
case (year > 1):
return `${year} years ago`; // 2 years ago
default:
return getFormattedDate(date); // January 10th 2022 at 10:20pm
}
}


return timeAgo(date);
};


console.log(showTimeAgo("2022-06-20T13:42:29-05:00"));-05:00"))

回复@Stas Parshin的答案,这是最好的答案,代码更少,但它在与typescript一起使用时有bug, Intl的.format函数需要2个输入

  1. < p >号码,

  2. 单元-即类型为“RelativeTimeFormatUnit”,因此如果你传递一个对象键typescript将通过错误说单元必须是类型为RelativeTimeFormatUnit,而不是类型为字符串,因此解决方法是使用类型来创建另一个相同类型的列表,其余的你可以查看代码… 快乐的编码。< / p >
    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
    };
    type RelativeTimeFormatUnit =
    | "year" | "years"
    | "quarter" | "quarters"
    | "month" | "months"
    | "week" | "weeks"
    | "day" | "days"
    | "hour" | "hours"
    | "minute" | "minutes"
    | "second" | "seconds"
    ;
    const units: RelativeTimeFormatUnit[] = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"]; // order matters here.
    const secondsElapsed = (date.getTime() - Date.now()) / 1000;
    for (let key in ranges) {
    let i = 0;
    if (ranges[key] < Math.abs(secondsElapsed)) {
    const delta = secondsElapsed / ranges[key];
    return formatter.format(Math.round(delta), units[i++]);
    }
    }
    }
    

这些答案大多不能解释复数(例如:复数)。“1分钟前”;当我们想要“1分钟前”;)

const MINUTE = 60;
const HOUR = MINUTE * 60;
const DAY = HOUR * 24;
const WEEK = DAY * 7;
const MONTH = DAY * 30;
const YEAR = DAY * 365;


function getTimeAgo(date) {
const secondsAgo = Math.round((Date.now() - Number(date)) / 1000);


if (secondsAgo < MINUTE) {
return secondsAgo + ` second${secondsAgo !== 1 ? "s" : ""} ago`;
}


let divisor;
let unit = "";


if (secondsAgo < HOUR) {
[divisor, unit] = [MINUTE, "minute"];
} else if (secondsAgo < DAY) {
[divisor, unit] = [HOUR, "hour"];
} else if (secondsAgo < WEEK) {
[divisor, unit] = [DAY, "day"];
} else if (secondsAgo < MONTH) {
[divisor, unit] = [WEEK, "week"];
} else if (secondsAgo < YEAR) {
[divisor, unit] = [MONTH, "month"];
} else {
[divisor, unit] = [YEAR, "year"];
}


const count = Math.floor(secondsAgo / divisor);
return `${count} ${unit}${count > 1 ? "s" : ""} ago`;
}

然后你可以这样使用它:

const date = new Date();
console.log(getTimeAgo(date));
// 1 second ago
// 2 seconds ago
// 1 minute ago
// 2 minutes ago
// ...

如果你已经在使用date-fns,你可以使用内置的formatDistance(以前是distanceInWords):

const date1 = new Date(2014, 6, 2);
const date2 = new Date(2015, 0, 1);
const options = { addSuffix: true }
const result = formatDistance(date1, date2, options);
//=> '6 months ago'

以上答案适用于旧的java脚本。但它在新的EC6 JavaScript或TypeScript上运行得不太好。下面是一个非常简短和简单的函数,用于最新的JavaScript, TypeScript, AngularJs, ReactJs和NodeJs,根据给定的日期和时间返回时间。

  public timeAgo(date) {
var seconds = Math.floor((new Date().getTime() - new Date(date).getTime()) / 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";
}


console.log(timeAgo('2022-08-12 20:50:20'));
// 2 hours ago, as per the given date time string.
    const timeHandler = (time: any) => {
var a = moment(); //now
var b = moment.utc(time);
const sec = a.diff(b, 'seconds');
const minuts = a.diff(b, 'minutes');
const hours = a.diff(b, 'hours');
const days = a.diff(b, 'days');
const weeks = a.diff(b, 'weeks');
return weeks == 0
? days == 0
? hours == 0
? minuts == 0
? sec >= 0 && `${sec}s ago`
: `${minuts}m ago`
: `${hours}h ago`
: `${days}d ago`
: `${weeks}w ago`;
};


console.log(timeHandler('2022-11-11T12:11:06.6103808'))