Javascript-bibliotek för människovänlig relativ datumformatering


Jag skulle vilja visa några datum relativt det aktuella datumet i ett användarvänligt format.

Exempel på människovänliga relativa datum:

  • För 10 sekunder sedan
  • Om 20 minuter
  • 1 dag sedan
  • för 5 veckor sedan
  • 2 månader sedan

I grund och botten troget bevara den högsta storleksordningen (och helst bara flytta upp enheter när man passerar 2 av dessa enheter - 5 veckor istället för 1 månad).

Även om jag skulle kunna leva med ett bibliotek som hade mindre kontroll och ännu mer vänliga datum som:

  • igår
  • imorgon
  • förra veckan
  • för några minuter sedan
  • om några timmar

Finns det några populära bibliotek för detta?

Svar #1

Sedan jag skrev detta svar finns ett välkänt bibliotek tillgängligt som heter moment.js.

Det finns bibliotek tillgängliga, men det är trivialt att implementera det själv. Använd bara ett par villkor.

Anta att date är ett instansierat Date-objekt för den tidpunkt du vill jämföra mot.

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

Du skulle behöva anpassa detta för att hantera framtida datum.

Svar #2

Jag skrev moment.js, ett datumbibliotek som gör detta. Det är ungefär 5KB (2011) 52KB (2019), och fungerar i webbläsare och i Node. Det är också förmodligen det mest populära och kända datumbiblioteket för JavaScript.

Det stöder timeago, formatering, parsning, frågning, manipulering, i18n, etc.

Timeago (relativ tid) för datum i det förflutna görs med moment().fromNow(). Till exempel, för att visa 1 januari 2019 i timeago-format:

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

Timeago-strängarna kan anpassas med moment.updateLocale(), så du kan ändra dem som du vill.

Gränserna är inte vad frågan begär ("5 veckor" vs. "1 månad"), men det är dokumenterat vilka strängar som används för vilken tidsperiod.

Svar #3

Här är något från John Resig - http://ejohn.org/blog/javascript-pretty-date/

REDIGERA (2014-06-27): Som en uppföljning på kommentaren från Sumurai8 - även om den länkade sidan fortfarande fungerar, här är utdraget för pretty.js som länkas från artikeln ovan:

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

Användning:

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

Utdrag från artikeln om användning:

Exempel på användning

I följande exempel gör jag så att alla ankare på sidan, som har en titel med ett datum i sig, har ett snyggt datum som sin inre text. Dessutom fortsätter jag att uppdatera länkarna var 5:e sekund efter att sidan har laddats.

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

Med jQuery:

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

Faiz: Gjorde några ändringar i den ursprungliga koden, buggfixar och förbättringar.

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

Svar #4

sugar.js har fantastiska funktioner för datumformattering.

Inte nog med det, det tillhandahåller också vanliga allmänna funktioner som strängformatering, nummerformatering, etc. som är bekväma att använda.

Relaterade artiklar