Formater une date en Javascript

in JavaScript fr

Mon choix par défaut pour formater des dates en JavaScript a longtemps été Moment.js . C’est une solution vraiment complète pour gérer les dates ; et je l’utilise encore côté serveur. Mais 16.6k gzipé, ou 62.4 k avec toutes les locales pour une seule fonctionnalité ? C’est trop pour moi.

Le coût du téléchargement et du parsing de ce code n‘est pas insurmontable en soit. Mais additionné à tout le reste, on finit par avoir une application trop lourde. C’est mauvais pour les utilisateurs. Depuis pas mal de temps, j’utilise mon petit module pour le formatage. C’est loin de couvrir toutes les fonctions de Moment.js. Mais ça fait le job pour le formatage.

Le code du module :

/**
 * Format a Date
 * @param  *        date    Anything that can be parsed
 *                          to a Date Object in JavaScript
 *                          2017-01-01, 1483228800000...
 * @param  String   format  See switch statement for
 *                          accepted values
 * @return String   formated Date
 */

const ensureDoubleDigit = value => value < 10 ? '0' + value : value;
const monthsShort = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
const monthsLong = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ];
const weekdaysShort = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
const weekdaysLong = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ];

export default function formatDate( dateInput, format ) => {

    const date = new Date( dateInput );

    return format.split( ' ' ).map(
        token => {
            switch ( token ) {
            case '':
                return ' ';
                break;
            case 'YYYY': // Full year
                return date.getFullYear();
                break;
            case 'M': // Month number
                return date.getMonth() + 1;
                break;
            case 'MM': // Month short
                return monthsShort[ date.getMonth() ];
                break;
            case 'MMM': // Month long
                return monthsLong[ date.getMonth() ];
                break;
            case 'D': // Month day
                return date.getDate();
                break;
            case 'WD': // Week day short
                return weekdaysShort[ date.getDay() ];
                break;
            case 'WDD': // Week day long
                return weekdaysLong[ date.getDay() ];
                break;
            case 'h': // Hours
                return date.getHours();
                break;
            case 'hh': // Hours double digits
                return ensureDoubleDigit( date.getHours() );
                break;
            case 'm': // Minutes
                return date.getMinutes();
                break;
            case 'mm': // Minutes double digits
                return ensureDoubleDigit( date.getMinutes() );
                break;
            case 's': // Seconds
                return date.getSeconds();
                break;
            case 'ss': // Seconds double digits
                return ensureDoubleDigit( date.getSeconds() );
                break;
            default: // For unknown tokens just return them
                return token;
                break;
            }
        }
    ).join( '' );

};


formatDate( new Date(), 'YYYY - M - D  //  hh : mm : ss' );
    >    2017-5-31 // 10:29:08

Remarquez qu’il faut deux espaces pour en obtenir un dans le format final. C’est pour éviter d’avoir à recourir à des expressions régulières complexes. Un simple split et un switch font le travail.

On peut vouloir éditer le module pour ajouter ou modifier des possibilités de formatage. Par exemple, ajouter YM pour le numéro de la semaine dans l’année (de 1 à 52). Si vous préférez avoir les jours sur une ou deux lettres au lieu de trois, il suffit d’éditer les données correspondantes. On a souvent des besoins qui requièrent des petits hacks sur les librairies que l’on utilise. Écrire ses modules a des inconvénients ; mais ça a le bénéfice de la modularité.

Pour internationaliser, ce n’est pas plus compliqué. Par exemple pour les jours de la semaine :

const weekdaysShort = () => {
    switch( global.locale ) {
        // Là où la locale est stockée
        // peut-être dans un store redux ?
        case 'en' :
            return [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
            break;
        case 'fr' :
            return [ 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam' ];
            break;

    }
}