Skip to content
Advertisement

moment.js date validation from array of formats

I need to test an input for proper date format. I want to accept several date formats so I created a validating function that test if at least one of the formats is OK and in that case return true. I use moment.js to test the date. When I simply type the condition with hard-coded string date formats, the function works properly:

var multiDateValidator = function (value)
{
    if ((moment(value, 'DD/MM/YYYY', true).isValid()) ||
        (moment(value, 'D/M/YYYY', true).isValid()) ||
        (moment(value, 'DD.MM.YYYY', true).isValid()) ||
        (moment(value, 'D.M.YYYY', true).isValid()) ||
        (moment(value, 'DD. MM. YYYY', true).isValid()) ||
        (moment(value, 'D. M. YYYY', true).isValid())) {
        return true;
    }

    return false;
};

But if I want to use the list of allowed date formats, it doesn’t work, it never returns true.

var allowedDateFormats = ['DD/MM/YYYY', 'D/M/YYYY', 'DD.MM.YYYY', 'D.M.YYYY', 'DD. MM. YYYY', 'D. M. YYYY'];

var multiDateValidator = function (value)
{
    allowedDateFormats.forEach(function(dateFormat)
    {
        if (moment(value, dateFormat, true).isValid()) {
            return true;
        }
    });

    return false;
};

What’s wrong with the second function? I know I’m not too good at JavaScript, but it should work, shouldn’t it?

Advertisement

Answer

The is no need to use for or forEach loop. Moment provides moment(String, String[], String, Boolean); method for parsing string using multiple formats.

As the docs says:

If you don’t know the exact format of an input string, but know it could be one of many, you can use an array of formats.

Starting in version 2.3.0, Moment uses some simple heuristics to determine which format to use. In order:

  • Prefer formats resulting in valid dates over invalid ones.
  • Prefer formats that parse more of the string than less and use more of the format than less, i.e. prefer stricter parsing.
  • Prefer formats earlier in the array than later.

Here a working live sample:

var allowedDateFormats = ['DD/MM/YYYY', 'D/M/YYYY', 'DD.MM.YYYY', 'D.M.YYYY', 'DD. MM. YYYY', 'D. M. YYYY'];

var multiDateValidator = function (value){
  return moment(value, allowedDateFormats, true).isValid();
};

var test = ['01/01/2017', '01.01.2017', '2017-Jan-01'];
for(var i=0; i<test.length; i++){
  console.log(test[i], multiDateValidator(test[i]));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement