91 votes

Javascript horodatage en temps relatif

Je suis à la recherche d'un joli extrait de code JS pour convertir un horodatage (par exemple à partir de l'API Twitter) en un temps relatif convivial pour l'utilisateur (par exemple, il y a 2 secondes, il y a une semaine, etc).

Est-ce que quelqu'un serait prêt à partager certaines de ses méthodes préférées (de préférence sans utiliser de plugins) ?

0 votes

6voto

kigiri Points 628
const units = [
  ['year', 31536000000],
  ['month', 2628000000],
  ['day', 86400000],
  ['hour', 3600000],
  ['minute', 60000],
  ['second', 1000],
]

const rtf = new Intl.RelativeTimeFormat('fr', { style:'narrow'})
const relatime = elapsed => {
  for (const [unit, amount] of units) {
    if (Math.abs(elapsed) > amount || unit === 'second') {
      return rtf.format(Math.round(elapsed/amount), unit)
    }
  }
}

had some fun golfing it 192b hehe

const relatime = e=>{for(let[u,a]of Object.entries({year:31536e6,month:2628e6,day:864e5,hour:36e5,minute:6e4,second:1e3})){if(Math.abs(e)>a||a===1e3){return new Intl.RelativeTimeFormat('fr',{style:'narrow'}).format(~~(e/a),u)}}}

I also tested a functionnal version while golfing:

const rtf = new Intl.RelativeTimeFormat('fr', { style:'narrow'})
const relatime = Object.entries({year:31536e6,month:2628e6,day:864e5,hour:36e5,minute:6e4,second:1e3})
  .reduce((f, [unit, amount]) => amount === 1e3
    ? f(elapsed => rtf.format(Math.round(elapsed/amount), unit))
    : next => f(e => Math.abs(e) < amount
      ? next(elapsed)
      : rtf.format(Math.round(elapsed/amount), unit)), _=>_)

All right i really have to get back to work now...

3voto

Nitin Jadhav Points 124

Réponse MomentJS


Pour les utilisateurs de Moment.js, il existe la fonction fromNow() qui renvoie "x jours" ou "il y a x heures" à partir de la date/heure actuelle.

moment([2007, 0, 29]).fromNow();     // Il y a 4 ans
moment([2007, 0, 29]).fromNow(true); // 4 ans

2voto

Shaun Scovil Points 357

Comme l'auteur du post original, j'ai tendance à éviter les plugins et packages pour un code qui semble trivial à écrire moi-même. Bien sûr, ensuite je finis par écrire mes propres packages.

J'ai créé ce package NPM pour pouvoir facilement convertir n'importe quelle date en une chaîne de temps relative (par exemple, "hier", "la semaine dernière", "il y a 2 ans"), avec des traductions pour l'internationalisation (i18n) et la localisation (l10n).

N'hésitez pas à parcourir le code source ; il s'agit d'un fichier assez petit unique. La plupart de ce qui se trouve dans le dépôt concerne les tests unitaires, le contrôle de version et la publication sur NPM.

export default class RTF {
    formatters;
    options;

    /**
     * @param options {{localeMatcher: string?, numeric: string?, style: string?}} options de l'objet Intl.RelativeTimeFormat()
     */
    constructor(options = RTF.defaultOptions) {
        this.options = options;
        this.formatters = { auto: new Intl.RelativeTimeFormat(undefined, this.options) };
    }

    // Les autres méthodes et propriétés sont également traduites

Fonctionnalités clés

  • Utilise le Intl.RelativeTimeFormat natif de JavaScript sous le capot, sans dépendances.
  • Formate n'importe quel objet Date, timestamp, ou représentation de date valide qui peut être analysé par Date.parse().
  • Fournit un middleware HTTP compatible avec des frameworks REST populaires comme Express et des outils i18n comme i18next.

Pourquoi utiliser ceci au lieu de Intl.RelativeTimeFormat.prototype.format() ?

Intl.RelativeTimeFormat.prototype.format() prend deux arguments : une valeur et des unités.

const rtf = new Intl.RelativeTimeFormat("en", { style: "narrow" });

expect(rtf.format(-1, "day")).toBe("1 day ago");
expect(rtf.format(10, "seconds")).toBe("in 10 sec.");

Pour convertir un objet Date, un timestamp, ou une chaîne de date, vous devez écrire beaucoup de code redondant. Cette bibliothèque vous évite ce casse-tête, et peut également être utilisée pour générer une fonction middleware pour votre API REST qui fonctionne avec votre bibliothèque i18n.

1voto

Diego Castillo Points 29

Pour ceux qui sont intéressés, j'ai fini par créer un assistant Handlebars pour cela. Utilisation :

    {{#beautify_date}}
        {{timestamp_ms}}
    {{/beautify_date}}

Assistant :

    Handlebars.registerHelper('beautify_date', function(options) {
        var timeAgo = new Date(parseInt(options.fn(this)));

        if (Object.prototype.toString.call(timeAgo) === "[object Date]") {
            if (isNaN(timeAgo.getTime())) {
                return 'Non valide';
            } else {
                var seconds = Math.floor((new Date() - timeAgo) / 1000),
                intervals = [
                    Math.floor(seconds / 31536000),
                    Math.floor(seconds / 2592000),
                    Math.floor(seconds / 86400),
                    Math.floor(seconds / 3600),
                    Math.floor(seconds / 60)
                ],
                times = [
                    'année',
                    'mois',
                    'jour',
                    'heure',
                    'minute'
                ];

                var key;
                for(key in intervals) {
                    if (intervals[key] > 1)  
                        return intervals[key] + ' ' + times[key] + 's depuis';
                    else if (intervals[key] === 1) 
                        return intervals[key] + ' ' + times[key] + ' depuis';
                }

                return Math.floor(seconds) + ' secondes depuis';
            }
        } else {
            return 'Non valide';
        }
    });

1voto

abumalick Points 416

Si vous avez besoin de multilinguisme et que vous ne voulez pas ajouter une grande bibliothèque comme moment. intl-relativeformat de yahoo est une bonne solution.

var rf = new IntlRelativeFormat('en-US');

var posts = [
    {
        id   : 1,
        title: 'Un article de blog',
        date : new Date(1426271670524)
    },
    {
        id   : 2,
        title: 'Un autre article de blog',
        date : new Date(1426278870524)
    }
];

posts.forEach(function (post) {
    console.log(rf.format(post.date));
});
// => "il y a 3 heures"
// => "il y a 1 heure"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X