Validating a ISO_8601 full date with momentJS?

Viewed 1172

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)

2 Answers

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" />
};

I would just add format function call and specify the format you want to check.

const date = moment(dateValue, moment.ISO_8601, true).format('DD-MM-YYYY') moment(date).isValid()

Have you tried this yet?

Related