Jak sformatować czas od xxx, np. „4 minuty temu” podobny do witryn Stack Exchange

210

Pytanie brzmi: jak sformatować JavaScript Datejako ciąg znaków określający upływ czasu, podobnie jak sposób wyświetlania czasu w przepełnieniu stosu.

na przykład

  • 1 minuta temu
  • 1 godzinę temu
  • 1 dzień temu
  • 1 miesiąc temu
  • 1 rok temu
Sky Sanders
źródło
14
momentjs.com
atilkan
Przydatna dla: Intl.RelativeTimeFormat.prototype.format().
Константин Ван

Odpowiedzi:

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
źródło
3
@hello - tak, pojedynczy punkt wyjścia ma swoje zalety, gdy nie przeszkadza. ci, którzy obecnie traktują to zbyt poważnie, nie rozumieją pochodzenia maksymy.
Sky Sanders,
36
Dobra funkcja, ale kilka uwag. Zmieniono pierwszy wiersz na: var seconds = Math.floor (((new Date (). GetTime () / 1000) - date)), aby działał z uniksowymi znacznikami czasu. I musiał zmienić intval> 1 na intval> = 1, w przeciwnym razie pokazywałoby 75 minut (od 1 do 2 godzin).
PanMan
3
@PanMan, jeśli po prostu zmienisz> na> =, skończysz z czasami takimi jak „1 minuta”. Zamieściłem zmodyfikowaną wersję tej odpowiedzi, która warunkowo dodaje „s”: stackoverflow.com/a/23259289/373655
rob
Nigdy nie używaj konkatenacji ciągów, ale String.format, jeśli chcesz rozwiązania, które można internacjonalizować
rds
Co jeśli chcę umieścić go w klasie div? Co mogę zrobić? Przepraszam, nie jestem profesjonalistą w javascript. Próbowałem tego document.getElementsByTagName ('. Sampleclass') [0] .innerHTML = timeSince (date); oraz ten document.getElementById ('idname') [0] .innerHTML = timeSince (date); ale to nie działa. Jakaś pomoc? Dziękuję Ci.
x'tian
119

W tym przypadku może to być przesada, ale jeśli okazja pokazuje, że moment.js jest po prostu niesamowity!

Moment.js to biblioteka czasu javascript, aby użyć jej w takim scenariuszu, wykonaj następujące czynności:

moment(yourdate).fromNow()

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

Dodatek 2018 : Luxon to nowa nowoczesna biblioteka i warto ją zobaczyć!

Fabiano Soriani
źródło
Witam, używam waszej odpowiedzi, aby uzyskać różnicę czasu. Co mogę zrobić, jeśli potrzebuję tylko pierwszych liter datelike roku jako y, miesiąca im oraz dnia jako d?
Nodirabegimxonoyim
57

Nie sprawdziłem (choć nie byłoby to trudne), ale myślę, że witryny Stack Exchange używają jquery.timeagowtyczki do tworzenia tych ciągów czasowych .


Wtyczka jest dość łatwa, jest czysta i aktualizuje się automatycznie.

Oto krótka próbka (ze strony głównej wtyczki):

Najpierw załaduj jQuery i wtyczkę:

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

Teraz dołączmy go do znaczników czasu w DOM gotowych:

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

To zmieni wszystkie abbrelementy z klasą timeagoi znacznikiem czasu ISO 8601 w tytule: <abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr>w coś takiego: <abbr class="timeago" title="July 17, 2008">about a year ago</abbr>co daje: około rok temu. W miarę upływu czasu znaczniki czasu będą automatycznie aktualizowane.

Maxim Zaslavsky
źródło
11
Nie wszyscy korzystają z JQuery.
2
Nie ma sensu mieć tego jako wtyczki jquery.
AlexG
57

Spowoduje to wyświetlenie przeszłych i poprzednich formatów czasu, takich jak „2 dni temu”, „10 minut od teraz”, i możesz przekazać mu obiekt Date, numeryczny znacznik czasu lub ciąg daty

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

Mózg
źródło
Zastąpić ostatni wiersz return time;z format = time_formats[time_formats.length - 1]; return Math.floor(seconds / format[2]) + ' ' + format[1] + ' ' + token;na wieki powrotów dla dużych rozpiętości czasu zamiast milisekund.
Aquila Sands,
Bardzo dobrze! Chociaż zauważyłem w iOS, gdy jest używany z filtrem kątowym, przeglądarka zwraca tutaj NaN. Naprawia to: czas = + nowa data (time.replace (/ - / g, '/'));
Tiago,
Świetnie, ale zadanie w tym, że pętla while jest brzydka i myląca. Zmiana na pętlę forEach byłaby lepsza
Martin Dawson
25

Oto niewielka modyfikacja rozwiązania Sky Sander, która pozwala wprowadzić datę jako ciąg znaków i może wyświetlać zakresy takie jak „1 minuta” zamiast „73 sekund”

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

obrabować
źródło
2
Nie działa to przez kilka sekund, ponieważ interwał pozostawia 0 od interval = Math.floor(seconds / 60);. Dodałem interval = seconds;do finału elsei działa dobrze.
howard10
2
Jeśli interwał wynosi 0, należy również dodać „s”.
JW.
To jest niesamowite. Do TS musiałem dodać jednego operatoralet seconds = Math.floor((+new Date() - date) / 1000);
Ben Racicot
Dlaczego sprawdzasz nawet interval === 0w ostatnim if?
smartmouse
1
@smartmouse tak, że będzie powiedzieć „0 sekund” zamiast „0 sekund”
rob
14

Możesz spojrzeć na humanized_time_span: https://github.com/layam/js_humanized_time_span

Jest niezależny od ram i w pełni konfigurowalny.

Wystarczy pobrać / dołączyć skrypt, a następnie możesz to zrobić:

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'

a nawet to:

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"

Przeczytaj dokumentację, aby uzyskać więcej informacji.

Will Tomlins
źródło
4
Oznacza to tylko, że nie polega on na jQuery ani nawet na DOM.
Will Tomlins,
Daje mi NaN years agodlaczego?
do diabła mam to ... twój przykład użycia jest zły. w rzeczywistości ograniczasz pierwsze cyfry ukośnikiem zamiast „-” .. w ten sposóbhumanized_time_span("2011/05/11 12:00:00")
to może zależeć od twojej lokalnej kultury i różnić się między użytkownikami :)
mikus
13

Zmieniłem powyższą funkcję na

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

W przeciwnym razie pokazywałby coś w rodzaju „75 minut” (od 1 do 2 godzin). Zakłada również, że data wejścia jest datownikiem uniksowym.

PanMan
źródło
Proszę podzielić datę przez 1000.
Użyłem tego, gdy dane pochodziły z bazy danych z uniksowymi znacznikami czasu w kilka sekund. Gdy jest w milisekundach, musisz podzielić przez 1000.
PanMan
11

Bardzo czytelny i kompatybilny z różnymi przeglądarkami kod:

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

użytkownik 1012181
źródło
Zauważ, że powoduje to pewne błędne założenia, takie jak codzienne bycie 86 400 sekund (chyba że strefa czasowa jest ustawiona na UTC, nie zawsze jest to prawdą dzięki UTC)
ItalyPaleAle
10

Krótsza wersja używana przez 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
źródło
2
Najkrótszy przedział trwa zero sekund - skutkuje to podzieleniem przez błąd zerowy.
apk
@apk ma rację. <60 sekund drukujeInfinity seconds ago
leonheess
8

od teraz paramerem znacznika czasu 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;
    }

}
pkarc
źródło
5

Wersja kodu ES6 dostarczona przez @ 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`;
};

Edytowane z sugestiami @ ibe-vanmeenen. (Dzięki !)

Geoffroy Warin
źródło
Powinieneś także dołączyć „sekundę: 1” do EPOCHS, inaczej pęknie, jeśli będzie to mniej niż 1 minutę temu :). Ostatnie 3 zmienne mogą być również stałym nie?
Ibe Vanmeenen,
1
Ponadto EPOCHS powinien być tablicą, ponieważ obiekty nie gwarantują kolejności właściwości. Zapisałem moje zmiany w gist.github.com/IbeVanmeenen/4e3e58820c9168806e57530563612886 . Możesz je skopiować, aby edytować tę odpowiedź :)
Ibe Vanmeenen,
5

Prosta i czytelna wersja:

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
źródło
3

Piszę jeden z js i pythonem, używany w dwóch projektach, bardzo ładny i prosty: prosta biblioteka (mniej niż 2kb) używana do formatowania daty za pomocą *** time agoinstrukcji.

proste, małe, łatwe w użyciu i dobrze przetestowane.

  1. npm install timeago.js

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

  3. użyj interfejsu API format.

Próba:

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

Możesz także renderować w czasie rzeczywistym.

var timeagoIns = timeago();
timeagoIns.render(document.querySelectorAll('time'));
narzędzie
źródło
Od wersji 4.0 możesz zamiast tego użyć zniszczonego importu:import { format, render, cancel, register } from 'timeago.js';
cmfolio
3

Chociaż pytanie zostało zadane już dawno temu, napisanie tej odpowiedzi z nadzieją, że komuś pomoże.

Podaj datę, od której chcesz zacząć liczyć. Korzystanie moment().fromNow()z momentjs : (Zobacz więcej informacji tutaj )

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

Jeśli chcesz zmienić informacje podane dla dat od Teraz piszesz swój własny względny czas dla chwili.

Na przykład w moim przypadku chciałem wydrukować 'one month ago'zamiast 'a month ago'( podany przez moment (d) .fromNow () ). W takim przypadku możesz napisać coś podanego poniżej.

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

UWAGA : Kod napisałem dla projektu w Agular 6

Nodirabegimxonoyim
źródło
3

Można również użyć wtyczki dayjs relativeTime, aby rozwiązać ten problem.

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

dayjs.extend(relativeTime);
dayjs(dayjs('1990')).fromNow(); // x years ago
jjbskir
źródło
3

Powinno to poprawnie obsługiwać każdy ważny znacznik czasu, w tym Date.now (), jednostki pojedyncze i przyszłe daty. Pominąłem miesiące, ale te powinny być łatwe do dodania. Starałem się, aby było to możliwe do odczytania.

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

Będzie
źródło
2

Zmodyfikowałem wersję Sky Sanders. Operacje Math.floor (...) są oceniane w bloku 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();
            }
        }
Mojżesz Koledoye
źródło
jest literówka w ostatnim else if return days + "1 day ago";powinno byćreturn "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
źródło
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
źródło
1

Moje rozwiązanie ..

(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
źródło
1

Moje dźgnięcie w to na podstawie innych odpowiedzi.

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 Iwanow
źródło
0

Szukałem odpowiedzi na to pytanie i prawie wdrożyłem jedno z tych rozwiązań, ale kolega przypomniał mi o sprawdzeniu react-intl bibliotekę, ponieważ już z niej korzystamy.

Więc dodając do rozwiązań ... w przypadku korzystania z react-intlbiblioteki, mają <FormattedRelative>do tego komponent.

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

ewH
źródło
0

Oto co zrobiłem (obiekt zwraca jednostkę czasu wraz z jego wartością):

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
źródło