Format a Date in JavaScript

in JavaScript

My default choice for date formatting in JavaScript used to be Moment.js . It is a great library. A really complete solution to manage dates. I still use it server side. But 16.6k gziped, or 62.4 k with all the locales for one function ? That is way to much !

The cost of downloading and parsing that code is not that high. But if you add small stuff, you end up with a bloated web application. And that is not good for users. For some times, I’ve been using my own little module. This is nowhere near the capabilities of Moment.js. But the job is done for formatting.

Here is my small 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 ' ';
            case 'YYYY': // Full year
                return date.getFullYear();
            case 'M': // Month number
                return date.getMonth() + 1;
            case 'MM': // Month short
                return monthsShort[ date.getMonth() ];
            case 'MMM': // Month long
                return monthsLong[ date.getMonth() ];
            case 'D': // Month day
                return date.getDate();
            case 'WD': // Week day short
                return weekdaysShort[ date.getDay() ];
            case 'WDD': // Week day long
                return weekdaysLong[ date.getDay() ];
            case 'h': // Hours
                return date.getHours();
            case 'hh': // Hours double digits
                return ensureDoubleDigit( date.getHours() );
            case 'm': // Minutes
                return date.getMinutes();
            case 'mm': // Minutes double digits
                return ensureDoubleDigit( date.getMinutes() );
            case 's': // Seconds
                return date.getSeconds();
            case 'ss': // Seconds double digits
                return ensureDoubleDigit( date.getSeconds() );
            default: // For unknown tokens just return them
                return token;
    ).join( '' );


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

Notice how you need two spaces to have one space in the result. This is to avoid complex regular expression and parse with a simple switch statement.

You may want to extend it to add other formatting possibilities. YW for year week (from 1 to 52) could be added for example. You prefer having short days on one or two letters instead of three? Change it ! We often have specific needs that would require tweaking a library. When you write your own module, there are some pitfalls, but this is a benefit.

I18n is easy. For example, change the weekdays Array to be a function :

const weekdaysShort = () => {
    switch( global.locale ) {
        // Any way you store your current locale
        // maybe in a redux store ?
        case 'en' :
            return [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
        case 'fr' :
            return [ 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam' ];