Biblioteka JavaScript do przyjaznego dla człowieka formatowania dat względnych [zamknięte]

95

Chciałbym wyświetlić niektóre daty jako względne do daty bieżącej w formacie przyjaznym dla człowieka.

Przykłady dat względnych przyjaznych człowiekowi:

  • 10 sekund temu
  • Za 20 minut
  • 1 dzień temu
  • 5 tygodni temu
  • 2 miesiące temu

Zasadniczo wierne zachowanie najwyższego rzędu wielkości (i preferencyjnie przesuwanie jednostek w górę tylko po przejściu 2 z tych jednostek - 5 tygodni zamiast 1 miesiąca).

Chociaż mógłbym żyć z biblioteką, która miała mniejszą kontrolę i jeszcze bardziej przyjazne randki, takie jak:

  • wczoraj
  • jutro
  • zeszły tydzień
  • kilka minut temu
  • za kilka godzin

Jakieś popularne biblioteki?

rampion
źródło
Dlaczego „1 dzień temu” jest bardziej „przyjazny dla człowieka” niż zwykłe przedstawienie rzeczywistej daty i godziny?
RobG,
5
@RobG Powiedziałbym, że bardziej chodzi o unikanie przełączania kontekstów, np. Na stronie, która jest głównie tekstowa i jest czytana, zmiana kontekstu na np. Mm / dd / rr może spowodować pauzę. W tabeli danych użycie tego formatu może być bardziej czytelne. Zależy to również od tego, co czytelnik musi zrobić z datą, np. Czy „to wydarzyło się n dni temu” lub „to wydarzyło się przed 1 stycznia 1972 r.” Jest wykonalne lub w inny sposób odpowiednie w kontekście czytelnika.
wprl
Być może, ale mylące jest zobaczenie listy wydarzeń jako „Wczoraj… 3 dni temu… 10 / Maj…”. Nadal muszę przekonwertować je wszystkie na daty w mojej głowie, aby uzyskać obraz, kiedy wystąpiły. Daty są zwięzłe i precyzyjne, wartości „sprzed czasu” są konwersacyjne, nieprecyzyjne i zwykle są pomocne tylko w przypadku powiązanej daty. Może to tylko ja, ale może nie. :-)
RobG
6
Powiedziałbym, że zależy to od kontekstu. Przecież nie powiedzielibyście: „Poszedłem łowić 17 lutego 2014 roku”, gdyby to faktycznie było wczoraj. Tam jest znacznie więcej przerwy w mózgu. Ten rodzaj tekstu jest idealny na listę ostatnich wydarzeń.
Simon Williams,
2
@RobG Tylko nerdy tacy jak my myślą w ten sposób, a nie normalni ludzie.

Odpowiedzi:

94

Odkąd napisałem tę odpowiedź, dobrze znaną dostępną biblioteką jest moment.js .


Bibliotekidostępne , ale samodzielne wdrożenie jest trywialne. Po prostu użyj kilku warunków.

Załóżmy, że datejest to Dateobiekt, którego instancja ma miejsce w czasie, z którym chcesz dokonać porównania.

// Make a fuzzy time
var delta = Math.round((+new Date - date) / 1000);

var minute = 60,
    hour = minute * 60,
    day = hour * 24,
    week = day * 7;

var fuzzy;

if (delta < 30) {
    fuzzy = 'just then.';
} else if (delta < minute) {
    fuzzy = delta + ' seconds ago.';
} else if (delta < 2 * minute) {
    fuzzy = 'a minute ago.'
} else if (delta < hour) {
    fuzzy = Math.floor(delta / minute) + ' minutes ago.';
} else if (Math.floor(delta / hour) == 1) {
    fuzzy = '1 hour ago.'
} else if (delta < day) {
    fuzzy = Math.floor(delta / hour) + ' hours ago.';
} else if (delta < day * 2) {
    fuzzy = 'yesterday';
}

Będziesz musiał to dostosować, aby obsługiwać przyszłe daty.

Alex
źródło
9
Wczoraj jest przed ostatnią północą, a nie od 24 do 48 godzin temu.
mxcl,
@mmaclaurin Mine nigdy nie miał być kompletnym rozwiązaniem, tylko wskazówką we właściwym kierunku. Zrobię notatkę, aby zaktualizować ją później, lub jeśli chcesz, możesz edytować odpowiedź.
Alex
Proszę również spojrzeć na date-fns ! To świetna biblioteka, jeśli chcesz, aby Twoja baza kodu była niewielka, ponieważ zajmuje dużo mniej miejsca niż momentjs!
mesqueeb
1
Zmieniłem ten kod dokonać styl twitter getTimeAgofunkcji gist.github.com/pomber/6195066a9258d1fb93bb59c206345b38
pomber
87

Napisałem moment.js , bibliotekę dat, która to robi. Ma około 5 KB (2011) 52 KB (2019) i działa w przeglądarkach oraz w Node. Jest to również prawdopodobnie najpopularniejsza i najbardziej znana biblioteka dat dla JavaScript.

Obsługuje timeago, formatowanie, parsowanie, zapytania, manipulowanie, i18n itp.

Timeago (czas względny) dla dat z przeszłości jest zakończony moment().fromNow(). Na przykład, aby wyświetlić 1 stycznia 2019 r. W formacie timeago:

let date = moment("2019-01-01", "YYYY-MM-DD");
console.log(date.fromNow());
<script src="https://momentjs.com/downloads/moment.min.js"></script>

Ciągi timeago można dostosować za pomocą moment.updateLocale(), więc możesz je zmienić według własnego uznania.

Wartości graniczne nie są tym, czego żąda pytanie („5 tygodni” w porównaniu z „1 miesiącem”), ale jest udokumentowane, które ciągi znaków są używane w jakim przedziale czasu.

Timrwood
źródło
1
Brawa za sprawienie, by działał w przeglądarce i węźle !!!!
wprl
50
ha ta aktualizacja rozmiaru!
Askdesigners,
1
Proszę również spojrzeć na date-fns ! To świetna biblioteka, jeśli chcesz, aby Twoja baza kodu była niewielka, ponieważ zajmuje dużo mniej miejsca niż momentjs!
mesqueeb
Chociaż ta biblioteka jest dobra, odpowiedź nie zawiera wyjaśnienia, jak sformatować liczbę w sposób przyjazny dla człowieka przy użyciu jej
Zaklinacz kodu,
Czy zamierzasz również zaktualizować „wycofanie”? momentjs.com/docs/#/-project-status
Juan De la Cruz
17

Oto coś z John Resig - http://ejohn.org/blog/javascript-pretty-date/

EDYCJA (27.06.2014): W związku z komentarzem Sumurai8 - chociaż strona, do której prowadzi łącze, nadal działa, oto fragment linkupretty.js do z powyższego artykułu:

pretty.js

/*
 * JavaScript Pretty Date
 * Copyright (c) 2011 John Resig (ejohn.org)
 * Licensed under the MIT and GPL licenses.
 */

// Takes an ISO time and returns a string representing how
// long ago the date represents.
function prettyDate(time) {
    var date = new Date((time || "").replace(/-/g, "/").replace(/[TZ]/g, " ")),
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
        day_diff = Math.floor(diff / 86400);

    if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) return;

    return day_diff == 0 && (
    diff < 60 && "just now" || diff < 120 && "1 minute ago" || diff < 3600 && Math.floor(diff / 60) + " minutes ago" || diff < 7200 && "1 hour ago" || diff < 86400 && Math.floor(diff / 3600) + " hours ago") || day_diff == 1 && "Yesterday" || day_diff < 7 && day_diff + " days ago" || day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago";
}

// If jQuery is included in the page, adds a jQuery plugin to handle it as well
if (typeof jQuery != "undefined") jQuery.fn.prettyDate = function() {
    return this.each(function() {
        var date = prettyDate(this.title);
        if (date) jQuery(this).text(date);
    });
};

Stosowanie:

prettyDate("2008-01-28T20:24:17Z") // => "2 hours ago"
prettyDate("2008-01-27T22:24:17Z") // => "Yesterday"
prettyDate("2008-01-26T22:24:17Z") // => "2 days ago"
prettyDate("2008-01-14T22:24:17Z") // => "2 weeks ago"
prettyDate("2007-12-15T22:24:17Z") // => undefined

Fragment artykułu o stosowaniu:

Przykładowe użycie

W poniższych przykładach wszystkie kotwice w witrynie, które mają tytuł z datą, mają ładną datę jako tekst wewnętrzny. Ponadto nadal aktualizuję linki co 5 sekund po załadowaniu strony.

Z JavaScript:

function prettyLinks(){
    var links = document.getElementsByTagName("a");
    for ( var i = 0; i < links.length; i++ )
        if ( links[i].title ) {
            var date = prettyDate(links[i].title);
            if ( date )
                links[i].innerHTML = date;
        }
}
prettyLinks();
setInterval(prettyLinks, 5000);

Dzięki jQuery:

$("a").prettyDate();
setInterval(function(){ $("a").prettyDate(); }, 5000);

Faiz: Wprowadzono pewne zmiany w oryginalnym kodzie, poprawki błędów i ulepszenia.

function prettyDate(time) {
    var date = new Date((time || "").replace(/-/g, "/").replace(/[TZ]/g, " ")),
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
        day_diff = Math.floor(diff / 86400);
    var year = date.getFullYear(),
        month = date.getMonth()+1,
        day = date.getDate();

    if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
        return (
            year.toString()+'-'
            +((month<10) ? '0'+month.toString() : month.toString())+'-'
            +((day<10) ? '0'+day.toString() : day.toString())
        );

    var r =
    ( 
        (
            day_diff == 0 && 
            (
                (diff < 60 && "just now")
                || (diff < 120 && "1 minute ago")
                || (diff < 3600 && Math.floor(diff / 60) + " minutes ago")
                || (diff < 7200 && "1 hour ago")
                || (diff < 86400 && Math.floor(diff / 3600) + " hours ago")
            )
        )
        || (day_diff == 1 && "Yesterday")
        || (day_diff < 7 && day_diff + " days ago")
        || (day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago")
    );
    return r;
}
Hari Pachuveetil
źródło
1
Cześć Floyd, dodałem kilka zmian (poprawki błędów, ulepszenia) do Twojej odpowiedzi. Mam nadzieję, że nie masz nic przeciwko ...
Faiz
Dobry! Ale nie pracuj z typem liczbowym znacznika czasu, może potrzebujesz lepszego filtra, takiego jak if (typeof time == 'string') {time = time.replace (/ - / g, "/").replace(/[TZ]/ g, „”)); }
Arthur Araújo
Proszę, jak rozliczyć przyszłe daty? Jak za 2 dni.
Ikenna Emman
15

Sugar.js ma świetne funkcje formatowania daty.

Co więcej, zapewnia również popularne funkcje ogólnego przeznaczenia, takie jak formatowanie ciągów, formatowanie liczb itp., Które są wygodne w użyciu.

Hendy Irawan
źródło
1
zgadzam się, sugar.js zasługuje tutaj na więcej uwagi.
citykid
5

tutaj przykład cukier vs moment: w przypadku kalendarza wyświetlającego tygodnie potrzebowałem wartości z ostatniego poniedziałku:

moment.js

var m = moment().subtract("days", 1).sod().day(1) // returns a "moment"

sugar.js

var d = Date.past("monday") // returns a js Date object

Wolę cukier i po kilku miesiącach z moment.js przechodzę teraz na sugar.js. jest bardziej przejrzysty i ładnie integruje się z klasą Date w Javascripts.

Przypadki OP są obsługiwane przez obie biblioteki, dla sugar.js patrz http://sugarjs.com/dates

citykid
źródło
4

Ten skrypt js jest bardzo fajny. Wszystko, co musisz zrobić, to go wykonać. Wszystkie <time>tagi zostaną zmienione na daty względne i aktualizowane co kilka minut, aby czas względny był zawsze aktualny.

http://timeago.yarp.com/

boreq
źródło
1
Myślę, że to najlepsze rozwiązanie. Biblioteka jest bardzo aktywnie utrzymywana, oparta na / inspirowana kodem Resiga, jest bardzo mała, ma mnóstwo lokalizacji, integracja jest banalna.
John Bachir
4

Wygląda na to, że możesz użyć http://www.datejs.com/

Mają przykład na stronie głównej, który robi dokładnie to, co opisujesz!

EDYCJA: Właściwie myślę, że odwróciłem twoje pytanie w mojej głowie. W każdym razie myślę, że możesz to sprawdzić, ponieważ i tak jest to naprawdę świetna biblioteka!

EDYCJA x2: Powtórzę to, co powiedzieli inni, http://momentjs.com/ jest prawdopodobnie najlepszym dostępnym obecnie wyborem.

EDYCJA x3: Nie używałem date.js od ponad roku. Używam momentjs wyłącznie do wszystkich moich potrzeb związanych z randkami.

RoboKozo
źródło
Niezła propozycja lib. Internacjonalizacja to zdecydowanie plus.
Stephen
Date.js też był moją pierwszą myślą, ale nie widzę sposobu, aby przejść z tego numeru do formatu - chociaż może być ukryty gdzieś w dokumentach.
rampion
Date.js jest znany z poważnych błędów i nie można mu ufać w środowiskach produkcyjnych. Wiele frameworków przechodzi z Date.js na Moment.js
John Zabroski
Dowiedziałem się na własnej skórze, że datejs nie działa na Linuksie :(
fat fantasma