Bibliothèque Javascript pour une mise en forme de la date relative conviviale [fermé]


94

J'aimerais afficher certaines dates par rapport à la date actuelle dans un format convivial.

Exemples de dates relatives conviviales:

  • Il y a 10 secondes
  • Dans 20 minutes
  • il y a 1 jour
  • Il y a 5 semaines
  • il y a 2 mois

En gros, en préservant fidèlement l'ordre de grandeur le plus élevé (et de préférence, en ne déplaçant les unités que lorsque vous passez 2 de ces unités - 5 semaines au lieu de 1 mois).

Bien que je puisse vivre avec une bibliothèque qui avait moins de contrôle et des dates encore plus conviviales comme:

  • hier
  • demain
  • la semaine dernière
  • il y a quelques minutes
  • dans quelques heures

Des bibliothèques populaires pour cela?


Pourquoi «il y a 1 jour» est-il plus «convivial» que de simplement présenter la date et l'heure réelles?
RobG

5
@RobG Je dirais qu'il s'agit plutôt d'éviter de changer de contexte, par exemple dans une page qui est principalement du texte et en cours de lecture, le changement de contexte sur par exemple mm / jj / aa peut provoquer une pause. Dans un tableau de données, l'utilisation de ce format peut être plus lisible. Cela dépend également de ce que le lecteur doit faire avec la date, par exemple si «cela s'est passé il y a n jours» ou «cela s'est produit avant le 1/1/1972» est exploitable ou autrement approprié au contexte du lecteur.
wprl

Peut-être, mais il est déroutant de voir une liste d'événements comme "Hier ... il y a 3 jours ... 10 / mai ...". J'ai encore besoin de les convertir toutes en dates dans ma tête pour avoir une image de quand elles se sont produites. Les dates sont concises et précises, les valeurs «il y a une heure» sont conversationnelles, manquent de précision et ne sont généralement utiles qu'avec la date associée. Peut-être que c'est juste moi, mais peut-être pas. :-)
RobG

6
Je dirais que cela dépend du contexte. Après tout, vous ne diriez pas "Je suis allé pêcher le 17 février 2014" si c'était effectivement hier. Il y a beaucoup plus de pause cérébrale là-bas. Ce type de texte est parfait pour une liste d'événements récents.
Simon Williams

2
@RobG Seuls les nerds comme nous pensent comme ça pas les gens normaux.

Réponses:


92

Depuis que j'ai écrit cette réponse, une bibliothèque bien connue est moment.js .


Il existe des bibliothèques disponibles , mais il est simple de l'implémenter vous-même. Utilisez juste une poignée de conditions.

Supposons que ce datesoit un Dateobjet instancié pour la durée avec laquelle vous souhaitez effectuer une comparaison.

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

Vous devrez l'adapter pour gérer les dates futures.


9
Hier, c'est avant le dernier minuit, pas entre 24 heures et 48 heures.
mxcl

@mmaclaurin Mine n'a jamais été conçue pour être une solution complète, juste un indicateur dans la bonne direction. Je ferai une note pour la mettre à jour plus tard, ou si vous le souhaitez, n'hésitez pas à modifier la réponse.
alex

Jetez également un œil à date-fns ! C'est une excellente bibliothèque si vous aimez garder votre base de code petite, car elle a une empreinte beaucoup plus faible que momentjs!
mesqueeb

1
J'ai changé ce code pour créer une getTimeAgofonction de style twitter gist.github.com/pomber/6195066a9258d1fb93bb59c206345b38
pomber le

85

J'ai écrit moment.js , une bibliothèque de dates qui fait cela. Il fait environ 5 Ko (2011) 52 Ko ( 2019) et fonctionne dans les navigateurs et dans Node. C'est probablement aussi la bibliothèque de dates la plus populaire et la plus connue pour JavaScript.

Il prend en charge timeago, formatage, analyse, interrogation, manipulation, i18n, etc.

Timeago (temps relatif) pour les dates dans le passé est terminé avec moment().fromNow(). Par exemple, pour afficher le 1er janvier 2019 au format timeago:

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

Les chaînes timeago sont personnalisables avec moment.updateLocale(), vous pouvez donc les modifier comme bon vous semble.

Les seuils ne correspondent pas à ce que demande la question («5 semaines» contre «1 mois»), mais il est documenté quant aux chaînes utilisées pour quelle plage de temps.


1
Félicitations pour l'avoir fait fonctionner dans le navigateur et le nœud !!!!
wprl

48
ha cette mise à jour de taille cependant!
Askdesigners

1
Jetez également un œil à date-fns ! C'est une excellente bibliothèque si vous aimez garder votre base de code petite, car elle a une empreinte beaucoup plus faible que momentjs!
mesqueeb

Aussi bonne que soit cette bibliothèque, la réponse n'inclut pas d'explication sur la façon de formater un nombre de manière conviviale en l'utilisant
Code Whisperer

16

Voici quelque chose de John Resig - http://ejohn.org/blog/javascript-pretty-date/

EDIT (27/06/2014): Suite au commentaire de Sumurai8 - bien que la page liée fonctionne toujours, voici l'extrait du pretty.jslien vers de l'article ci-dessus:

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

Usage:

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

Extrait de l'article sur l'utilisation:

Exemple d'utilisation

Dans les exemples suivants, je fais que toutes les ancres du site, qui ont un titre avec une date, ont une jolie date comme texte intérieur. De plus, je continue à mettre à jour les liens toutes les 5 secondes après le chargement de la page.

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

Avec jQuery:

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

Faiz: J'ai apporté quelques modifications au code d'origine, des corrections de bogues et des améliorations.

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

1
Salut Floyd, j'ai ajouté quelques modifications (correction de bogue, améliorations) à votre réponse. J'espère que ça ne vous dérange pas ..
Faiz

Bon! Mais ne travaillez pas avec le type numérique horodatage, peut-être avez-vous besoin d'un meilleur filtre comme if (typeof time == 'string') {time = time.replace (/ - / g, "/").replace(/[TZITED/) g, " ")); }
Arthur Araújo

15

sugar.js a d'excellentes fonctions de formatage de date.

Non seulement cela, il fournit également des fonctions générales communes telles que le formatage des chaînes, le formatage des nombres, etc. qui sont pratiques à utiliser.


1
d'accord, sugar.js mérite plus d'attention ici.
citykid

5

voici un exemple de sucre vs moment: pour un calendrier qui affiche des semaines, j'avais besoin de la valeur du dernier lundi:

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

Je préfère de loin le sucre et après quelques mois avec moment.js, je passe maintenant à sugar.js. il est plus clair et s'intègre bien avec la classe Date de Javascripts.

Les cas OP sont couverts par les deux bibliothèques, pour sugar.js voir http://sugarjs.com/dates


4

Ce script js est très agréable. Tout ce que vous avez à faire est de l'exécuter. Toutes les <time>balises seront changées en dates relatives et mises à jour toutes les quelques minutes, de sorte que l'heure relative sera toujours à jour.

http://timeago.yarp.com/


1
Je pense que c'est la meilleure solution. La bibliothèque est très activement maintenue, elle est basée sur / inspiré du code de Resig, elle est très petite, elle a des tonnes de localisations, c'est facile à intégrer.
John Bachir

4

On dirait que vous pourriez utiliser http://www.datejs.com/

Ils ont un exemple sur la page principale qui fait exactement ce que vous décrivez!

EDIT: En fait, je pense que j'ai inversé votre question dans ma tête. Dans tous les cas, je pense que vous pourriez le vérifier car c'est de toute façon une très bonne bibliothèque!

EDIT x2: Je vais faire écho à ce que les autres ont dit http://momentjs.com/ est probablement le meilleur choix disponible en ce moment.

EDIT x3: Je n'ai pas utilisé date.js depuis plus d'un an. J'utilise exclusivement momentjs pour tous mes besoins liés aux rendez-vous.


Belle suggestion de lib. L'internationalisation est certainement un plus.
Stephen

Date.js a également été ma première pensée, mais je ne vois aucun moyen de passer du nombre au format avec lui - bien qu'il puisse être caché quelque part dans la documentation.
rampion

Date.js est connu pour avoir de sérieux bogues et n'est pas fiable dans les environnements de production. De nombreux frameworks passent de Date.js à Moment.js
John Zabroski

J'ai appris à mes dépens que datejs ne fonctionne pas sous linux :(
fat fantasma
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.