Moment String Interpret

Benchmark created by Matt on


Description

Optimizations for Moment string interpretation

Preparation HTML

<script src="//momentjs.com/downloads/moment.min.js"></script>
<script src="//momentjs.com/downloads/moment-timezone.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Setup

var DEFAULT_TZ = 'Asia/Tokyo';
    
    var ISO_8601_DATE_REGEXP = /^(?:\d{4})(?:-(?:\d{2})(?:-(?:\d{2})(?:T(?:\d{2}):(?:\d{2})(?::(?:\d{2})(?:\.\d+)?)?(?:\-|\+)(?:\d{2}):(?:\d{2}))?)?)?$/;
    var DEFAULT_DATE_FORMATS_OLD = {
        'YYYY-MM-DD\\THH:mm:ssZ': /^(?:\d{4})-(?:\d{2})-(?:\d{2})T(?:\d{2}):(?:\d{2}):(?:\d{2})(?:\-|\+)(?:\d{2}):(?:\d{2})$/,
        'YYYY-MM-DD HH:mm:ss' : /^(?:\d{4})-(?:\d{2})-(?:\d{2})\s+(?:\d{2}):(?:\d{2}):(?:\d{2})$/,
        'YYYY-MM-DD': /^(?:\d{4})-(?:\d{2})-(?:\d{2})$/,
        'HH:mm:ss': /^(?:\d{2}):(?:\d{2}):(?:\d{2})$/,
        "M/D/YYYY": /^[01]?\d\/[0-3]?\d\/\d{4}$/,
        "M/D/YYYY HH:mm A": /^[01]?\d\/[0-3]?\d\/\d{4} \d{2}:\d{2} [aApP][mM]$/
    };
    
    var DEFAULT_DATE_FORMATS_NEW = {
        'HH:mm:ss': {
            regex: /^(\d{2}):(\d{2}):(\d{2})$/,
            match: ['hour', 'minute', 'second']
        },
        "M/D/YYYY": {
            regex: /^([01]?\d)\/([0-3]?\d)\/(\d{4})$/,
            match: ["month", "day", "year"]
        },
        "M/D/YYYY HH:mm A": {
            regex: /^([01]?\d)\/([0-3]?\d)\/(\d{4}) (\d{2}):(\d{2}) ([aApP][mM])$/,
            match: ["month", "day", "year", "hour", "minute", "ampm"]
        }
    };
    
    function oldToMoment(date, formats, tz)
    {
        var found = false;
        tz = tz || DEFAULT_TZ;
        formats = $.extend({}, DEFAULT_DATE_FORMATS_OLD, formats || {});
        $.each(formats, function(format, regex){
            if(found = date.match(regex))
            {
                date = moment.tz(date, format, tz);
                return false;
            }
        });
        return found && moment.isMoment(date) && date.isValid() && date;
    }
    
    function newToMoment(date, formats, tz)
    {
        var found = false;
        tz = tz || DEFAULT_TZ;
        if(found = date.match(ISO_8601_DATE_REGEXP))
        {
            var hasTz = date.indexOf('T') >= 0;
            var tmpDate = new Date(date);
            date = moment.tz(tmpDate, tz);
            if(!hasTz)
            {
                date.add(date.zone(), 'minutes');
            }
        }
        else
        {
            formats = $.extend({}, DEFAULT_DATE_FORMATS_NEW, formats || {});
            $.each(formats, function(format, regex){
                if(found = date.match(regex.regex || regex))
                {
                    if(regex.match)
                    {
                        var dateObj = {year: 1970, month: 1, day: 1, hour: 0, minute: 0, second: 0};
                        for(var i = 0; i < regex.match.length; i++)
                        {
                            dateObj[regex.match[i]] = found[i + 1];
                        }
                        if(dateObj.ampm && dateObj.hour)
                        {
                            if(dateObj.hour == 12)
                            {
                                if(dateObj.ampm.charAt(0).toLowerCase() == 'a')
                                {
                                    dateObj.hour = 0;
                                }
                            }
                            else if(dateObj.ampm.charAt(0).toLowerCase() == 'p')
                            {
                                dateObj.hour = parseInt(dateObj.hour) + 12;
                            }
                        }
                        var tmpDate = new Date(dateObj.year, dateObj.month - 1, dateObj.day, dateObj.hour, dateObj.minute, dateObj.second);
                        date = moment.tz(tmpDate, tz);
                        date.subtract(tmpDate.getTimezoneOffset() - date.zone(), 'minutes');
                    }
                    else
                    {
                        date = moment.tz(date, format, tz);
                    }
                    return false;
                }
            });
        }
        return found && moment.isMoment(date) && date.isValid() && date;
    }

Test runner

Ready to run.

Testing in
TestOps/sec
New ISO-8601 w/Timezone
newToMoment('2014-02-23T01:02:03-05:00');
ready
Old ISO-8601 w/Timezone
oldToMoment('2014-02-23T01:02:03-05:00');
ready
New ISO-8601 w/o Timezone
newToMoment('2014-02-23');
ready
Old ISO-8601 w/o Timezone
oldToMoment('2014-02-23');
ready
New non-ISO
newToMoment('02/03/2014');
ready
Old non-ISO
oldToMoment('02/03/2014');
ready
New non-ISO #2
newToMoment('02/03/2014 01:02 AM');
ready
Old non-ISO #2
oldToMoment('02/03/2014 01:02 AM');
ready
New non-ISO #3
newToMoment('01:02:03');
ready
Old non-ISO #3
oldToMoment('01:02:03');
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.