Come formattare il tempo da xxx ad es. “4 minuti fa” simile ai siti Stack Exchange

La domanda è come formattare una Date JavaScript come una stringa che indica il tempo trascorso simile al modo in cui vedi le ore visualizzate su Stack Overflow.

per esempio

  • 1 minuto fa
  • 1 ora fa
  • 1 giorno fa
  • 1 mese fa
  • 1 anno fa

 function timeSince(date) { var seconds = Math.floor((new Date() - date) / 1000); var interval = Math.floor(seconds / 31536000); if (interval > 1) { return interval + " years"; } interval = Math.floor(seconds / 2592000); if (interval > 1) { return interval + " months"; } interval = Math.floor(seconds / 86400); if (interval > 1) { return interval + " days"; } interval = Math.floor(seconds / 3600); if (interval > 1) { return interval + " hours"; } interval = Math.floor(seconds / 60); if (interval > 1) { return 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))); 

Potrebbe essere eccessivo in questo caso, ma se l’opportunità mostra moment.js è semplicemente fantastico!

Moment.js è una libreria datetime javascript, per utilizzarla per tale scenario, devi fare:

 moment(yourdate).fromNow() 

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

Aggiunta 2018 : Luxon è una nuova biblioteca moderna e potrebbe valere la pena dare un’occhiata!

Non ho controllato (anche se non sarebbe difficile), ma penso che i siti Stack Exchange usano il plugin jquery.timeago per creare queste stringhe temporali .


È abbastanza facile usare il plug-in, è pulito e si aggiorna automaticamente.

Ecco un rapido esempio (dalla home page del plugin):

Innanzitutto, carica jQuery e il plugin:

Ora, collegalo ai tuoi timestamp su DOM ready:

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

Ciò trasformsrà tutti gli elementi abbr con una class di timeago e un timestamp ISO 8601 nel titolo: July 17, 2008 in qualcosa di simile: about a year ago che produce: circa un anno fa. Con il passare del tempo, i timestamp si aggiorneranno automaticamente.

Questo mostrerà i formati precedenti e precedenti come “2 giorni fa” “10 minuti da ora” e puoi passarlo sia un object Date, un timestamp numerico o una stringa data

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

Ecco una leggera modifica sulla soluzione di Sky Sander che consente di inserire la data come stringa ed è in grado di visualizzare span come “1 minuto” anziché “73 secondi”

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

Potresti voler dare un’occhiata a humanized_time_span: https://github.com/layam/js_humanized_time_span

È agnostico quadro e completamente personalizzabile.

Basta scaricare / includere lo script e quindi puoi farlo:

 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' 

o anche questo:

 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" 

Leggi i documenti per maggiori informazioni.

Modificata la funzione sopra a

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

Altrimenti mostrerebbe cose come “75 minuti” (tra 1 e 2 ore). Inoltre ora assume che la data di input sia un timestamp Unix.

Codice compatibile molto leggibile e cross browser:

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

da ora, unix timestamp param,

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

Una versione più breve utilizzata da 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: 0 } ]; 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`; } 

Una versione ES6 del codice fornita da @ user1012181

 // Epochs const epochs = [ ['year', 31536000], ['month', 2592000], ['day', 86400], ['hour', 3600], ['minute', 60], ['second', 1] ]; // Get duration const getDuration = (timeAgoInSeconds) => { for (let [name, seconds] of epochs) { const interval = Math.floor(timeAgoInSeconds / seconds); if (interval >= 1) { return { interval: interval, epoch: name }; } } }; // Calculate 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`; }; 

Modificato con i suggerimenti di @ ibe-vanmeenen. (Grazie !)

Ho modificato la versione di Sky Sanders. Le operazioni Math.floor (…) vengono valutate nel blocco 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(); } } 

Ne scrivo uno con js e python, usato in due progetti, molto bello e semplice: una semplice libreria (meno di 2kb) usata per formattare la data con l’enunciato *** time ago .

semplice, piccolo, facile da usare e ben testato.

  1. npm install timeago.js

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

  3. usa il format API.

Campione:

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

Inoltre puoi eseguire il rendering in tempo reale.

 var timeagoIns = timeago(); timeagoIns.render(document.querySelectorAll('time')); 
 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"; } 

Stavo cercando una risposta a questo e ho quasi implementato una di queste soluzioni, ma un collega mi ha ricordato di controllare la libreria react-intl poiché la stavamo già utilizzando.

Quindi aggiungendo alle soluzioni … nel caso si stia usando la libreria react-intl , hanno un componente per questo.

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

Ecco cosa ho fatto (l’object restituisce l’unità di tempo insieme al suo valore):

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

La mia soluzione ..

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