Search code examples
javascriptmomentjsiso8601

Validating a ISO_8601 full date with momentJS?


I have the following code:

moment(dateValue, moment.ISO_8601, true).isValid()

Which works well, except for when i only have a date with the year and the month, i.e 2020-07, it still returns true.

How can i make it return true only if the value consists of at least a full date? (i.e 2020-07-15)


Solution

  • You could just define your own ISO_8601 format constant. The value of moment.ISO_8601 is a function which allows for partial timestamps. If you want to be strict, you just supply your own. I am reusing the HTML5 built-in "local-date" constants and appending a timezone option "Z" to the end.

    const ISO_8601 = moment.HTML5_FMT.DATETIME_LOCAL_MS + 'Z';
    const dateValue = new Date().toISOString();
    
    // Valid
    console.log(dateValue, '?', moment(dateValue, ISO_8601, true).isValid());
    
    // Invalid
    const yearMonth = dateValue.substring(0, 7);
    console.log(yearMonth, '?', moment(yearMonth, ISO_8601, true).isValid());
    
    // Valid
    const ymd = dateValue.substring(0, 10);
    console.log(ymd, '?', moment(ymd, moment.HTML5_FMT.DATE, true).isValid());
    
    // Valid
    const ts = '2012-02-02T13:30-01:00';
    const format = moment.HTML5_FMT.DATETIME_LOCAL + 'Z';
    console.log(ts, '?', moment(ts, format, true).isValid());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>

    Where:

    • moment.HTML5_FMT.DATETIME_LOCAL_MS"YYYY-MM-DDTHH:mm:ss.SSS"
    • moment.HTML5_FMT.DATE"YYYY-MM-DD"

    Here are all built-in HTML5 formats for moment (starting with version 2.20.0). These constants were added on December 16, 2017.

    // currently HTML5 input type only supports 24-hour formats
    hooks.HTML5_FMT = {
        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
        DATE: 'YYYY-MM-DD', // <input type="date" />
        TIME: 'HH:mm', // <input type="time" />
        TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
        TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
        WEEK: 'GGGG-[W]WW', // <input type="week" />
        MONTH: 'YYYY-MM', // <input type="month" />
    };