Como formatar a hora desde xxx, por exemplo, "4 minutos atrás", semelhante aos sites da Stack Exchange

210

A questão é como formatar um JavaScript Date como uma string indicando o tempo decorrido de maneira semelhante à maneira como você vê os horários exibidos no estouro de pilha.

por exemplo

  • 1 minuto atrás
  • 1 hora atrás
  • 1 dia atrás
  • 1 mês atrás
  • 1 ano atrás
Sky Sanders
fonte

Respostas:

324

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

Sky Sanders
fonte
3
@ olá - sim, o único ponto de saída tem suas virtudes quando não atrapalha. aqueles que levam isso muito a sério hoje em dia estão entendendo mal a origem da máxima.
Sky Sanders
36
Boa função, mas algumas observações. Alterou a primeira linha para: var seconds = Math.floor (((new Date (). GetTime () / 1000) - date))) para trabalhar com registros de data e hora unix. E precisava alterar o intval> 1 para intval> = 1, caso contrário, mostraria coisas como 75 minutos (entre 1 e 2 horas).
PanMan 23/11
3
@ Panman, se você alterar> para> =, você terminará com horários como "1 minuto". Eu publiquei uma versão modificada desta resposta que adiciona condicionalmente o "s": stackoverflow.com/a/23259289/373655
rob
Nunca use concatenação, mas String.format se você quer uma solução que pode ser internacionalizada
rds
E se eu quiser colocá-lo na classe div? O que eu posso fazer? Desculpe, eu não sou um profissional em javascript. Eu tentei este document.getElementsByTagName ('. Sampleclass') [0] .innerHTML = timeSince (date); e este document.getElementById ('idname') [0] .innerHTML = timeSince (date); mas não está funcionando. Qualquer ajuda? Obrigado.
Xtian #
119

Pode ser um exagero nesse caso, mas se a oportunidade aparecer moment.js é simplesmente incrível!

Moment.js é uma biblioteca de data e hora em javascript, para usá-la nesse cenário, você faria:

moment(yourdate).fromNow()

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

Adendo 2018 : Luxon é uma nova biblioteca moderna e pode valer a pena dar uma olhada!

Fabiano Soriani
fonte
Olá, estou usando sua resposta para obter um tempo diferente. O que posso fazer se eu precisar apenas das primeiras letras do ano semelhante ao ano como y, mês e dia e dia como d?
Nodirabegimxonoyim
57

Não marquei (embora não seja difícil), mas acho que os sites do Stack Exchange usam o jquery.timeagoplug - in para criar essas seqüências de tempo .


É muito fácil usar o plugin, é limpo e é atualizado automaticamente.

Aqui está uma amostra rápida (da página inicial do plug-in):

Primeiro, carregue o jQuery e o plug-in:

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

Agora, vamos anexá-lo aos seus registros de data e hora no DOM pronto:

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

Isso transformará todos os abbrelementos com uma classe timeagoe um carimbo de data / hora ISO 8601 no título: <abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr>em algo como isto: o <abbr class="timeago" title="July 17, 2008">about a year ago</abbr>que gera: cerca de um ano atrás. À medida que o tempo passa, os registros de data e hora são atualizados automaticamente.

Maxim Zaslavsky
fonte
11
Nem todo mundo usa JQuery.
2
Não faz sentido ter isso como um plugin jquery.
AlexGonzalez3
57

Isso mostrará os formatos de hora anteriores e anteriores, como '2 dias atrás' e 10 minutos a partir de agora ', e você pode transmiti-lo para um objeto Date, um carimbo de data / hora numérico ou uma string de 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)));

O cérebro
fonte
Substitua a última linha return time;por format = time_formats[time_formats.length - 1]; return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;para retornar séculos por longos períodos de tempo, em vez de milissegundos.
Aquila Sands
Muito agradável! Embora eu tenha notado no iOS, quando usado com angular como filtro, o navegador retorna NaN aqui. Isso corrige: time = + new Date (time.replace (/ - / g, '/'));
Tiago
Ótimo, mas a tarefa nesse loop while é feia e confusa. Mudar para um loop foreach seria melhor
Martin Dawson
25

Aqui está uma pequena modificação na solução Sky Sander que permite que a data seja inserida como uma sequência e é capaz de exibir intervalos como "1 minuto" em vez de "73 segundos"

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

roubar
fonte
2
Isso não funciona por segundos, pois o intervalo é deixado como 0 interval = Math.floor(seconds / 60);. Eu adicionei interval = seconds;na final elsee funciona bem.
howard10
2
Se o intervalo for 0, você também deve adicionar o "s".
JW.
Isso é incrível. Para TS eu tive que adicionar um operador unário emlet seconds = Math.floor((+new Date() - date) / 1000);
Ben Racicot
Por que você verifica até interval === 0no último if?
22418
1
@smartmouse para que ele diga "0 segundos" em vez de "0 segundo" #
rob rob
14

Você pode querer olhar para humanized_time_span: https://github.com/layam/js_humanized_time_span

É uma estrutura independente e totalmente personalizável.

Basta baixar / incluir o script e então você pode fazer isso:

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'

ou até isso:

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"

Leia os documentos para mais informações.

Will Tomlins
fonte
4
Apenas significa que ele não depende do jQuery ou mesmo de um DOM.
que seus amigos estão
Isso me dá o NaN years agoporquê?
caramba, eu entendi ... seu exemplo de uso está errado. na verdade, você delimita os primeiros números com barra em vez de "-" .. assimhumanized_time_span("2011/05/11 12:00:00")
pode depender de sua cultura local e diferem entre os usuários :)
mikus
13

A função acima foi alterada para

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

Caso contrário, mostraria coisas como "75 minutos" (entre 1 e 2 horas). Agora, ele também assume que a data de entrada é um carimbo de data / hora do Unix.

PanMan
fonte
Divida a data por 1000, por favor.
Eu usei isso onde os dados vieram de um banco de dados com timestamps Unix em segundos. Quando está em milissegundos Você precisa dividir por 1000.
Panman
11

Código legível e compatível com vários navegadores:

Como dado por @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
fonte
Note que este faz algumas suposições erradas, como todos os dias sendo 86.400 segundos (a menos que o fuso horário é definido para UTC, isso nem sempre é verdade, graças a UTC)
ItalyPaleAle
10

Uma versão mais curta usada por 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`;
}
Sam
fonte
2
O intervalo mais curto tem uma duração de zero segundos - isso resulta em uma divisão por erro zero.
apk
@apk está certo. <60 segundos impressos #Infinity seconds ago
leonheess 29/10/19
8

a partir de agora, 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;
    }

}
pkarc
fonte
5

Uma versão ES6 do código fornecida por @ 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`;
};

Editado com @ sugestões de ibe-vanmeenen. (Obrigado !)

Geoffroy Warin
fonte
Você também deve incluir "second: 1" no EPOCHS, caso contrário, ele será quebrado se houver menos de um minuto atrás :). Os últimos 3 vars também podem ser um constante não?
Ibe Vanmeenen
1
Além disso, o EPOCHS deve ser uma matriz, pois os objetos não garantem a ordem das propriedades. Guardei minhas alterações no gist.github.com/IbeVanmeenen/4e3e58820c9168806e57530563612886 . Você é bem-vindo para copiá-los para editar esta resposta :)
Ibe Vanmeenen
5

Versão simples e legível:

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")
            }
        }
    }
}
jcrs
fonte
3

Eu escrevo um com js e python, usado em dois projetos, muito agradável e simples: uma biblioteca simples (menos de 2kb) usada para formatar a data com a *** time agoinstrução.

simples, pequeno, fácil de usar e bem testado.

  1. npm install timeago.js

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

  3. use API format.

Amostra:

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

Além disso, você pode renderizar em tempo real.

var timeagoIns = timeago();
timeagoIns.render(document.querySelectorAll('time'));
uma ferramenta
fonte
A partir da import { format, render, cancel, register } from 'timeago.js';
versão
3

Embora a pergunta tenha sido feita há muito tempo, escrever esta resposta com esperança de ajudar alguém.

Passe a data em que deseja começar a contar. Uso moment().fromNow()de momentjs : (Veja mais informações aqui )

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

Se você deseja alterar as informações fornecidas para as datas em Agora, escreva seu tempo relativo personalizado por um momento.

Por exemplo, no meu próprio caso, eu queria imprimir em 'one month ago'vez de 'a month ago'( fornecido pelo momento (d) .fromNow () ). Nesse caso, você pode escrever algo abaixo.

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

NOTA : Escrevi meu código para o projeto no Agular 6

Nodirabegimxonoyim
fonte
3

Também pode usar o plug-in dayjs relativeTime para resolver isso.

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

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

Isso deve lidar adequadamente com qualquer carimbo de data / hora válido, incluindo Date.now (), unidades singulares e datas futuras. Fiquei meses de fora, mas esses devem ser fáceis de adicionar. Tentei mantê-lo o mais legível possível.

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

Vai
fonte
2

Eu modifiquei a versão do Sky Sanders. As operações Math.floor (...) são avaliadas no bloco 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();
            }
        }
Moses Koledoye
fonte
existe um erro de digitação no último caso, se return days + "1 day ago";deveria serreturn "1 day ago";
Marco Gurnari
2
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'));
Boumeziane Marouane
fonte
1
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";
}
Uygar
fonte
1

Minha solução ..

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

Minha facada nisso com base em outras respostas.

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;
}
Maksim Ivanov
fonte
0

Eu estava procurando uma resposta para isso e quase implementei uma dessas soluções, mas um colega me lembrou de verificar a react-intlbiblioteca, pois já a estávamos usando.

Então, adicionando às soluções ... no caso de você estar usando a react-intlbiblioteca, elas têm um <FormattedRelative>componente para isso.

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

ewH
fonte
0

Aqui está o que eu fiz (o objeto retorna a unidade de tempo junto com seu valor):

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

nateclonch
fonte