UNPKG

ember-validators

Version:
175 lines (146 loc) 5.32 kB
import validationError from 'ember-validators/utils/validation-error'; /** * @class Date * @module Validators */ /** * @method validate * @param {String|Date} value * @param {Object} options * @param {Boolean} options.allowBlank If true, skips validation if the value is empty * @param {String|Date} options.before The specified date must be before this date * @param {String|Date} options.onOrBefore The specified date must be on or before this date * @param {String|Date} options.after The specified date must be after this date * @param {String|Date} options.onOrAfter The specified date must be on or after this date * @param {String} options.format Input value date format - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat * - { dateStyle: 'long' } or { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } * If you need to obtain precision (just compare years), use { year: 'numeric' } * @param {String} options.errorFormat Error output date format. Defaults to options.format or { dateStyle: 'long' } */ export default function validateDate(value, options) { let { locale = 'en-us', format, allowBlank } = options; let { before, onOrBefore, after, onOrAfter } = options; let errorFormat = options.errorFormat || format || { dateStyle: 'long' }; if ((allowBlank && value === null) || value === undefined || value === '') { return true; } let date; if (!value) { if (format) { date = new Intl.DateTimeFormat(locale, format).format(new Date()); } date = new Date(); } else if (!isValidDate(new Date(value))) { return validationError('date', value, options); } else { date = parseAsDate(value, format, locale); } if (before) { const beforeCompare = parseAsDate(before, format, locale); if (!isBefore(date, beforeCompare)) { return validationError( 'before', value, Object.assign({}, options, { before: parseDateError(beforeCompare, errorFormat, locale), }) ); } } if (onOrBefore) { const onOrBeforeCompare = parseAsDate(onOrBefore, format, locale); if (!isSameOrBefore(date, onOrBeforeCompare)) { return validationError( 'onOrBefore', value, Object.assign({}, options, { onOrBefore: parseDateError(onOrBeforeCompare, errorFormat, locale), }) ); } } if (after) { const afterCompare = parseAsDate(after, format, locale); if (!isAfter(date, afterCompare)) { return validationError( 'after', value, Object.assign({}, options, { after: parseDateError(afterCompare, errorFormat, locale), }) ); } } if (onOrAfter) { const onOrAfterCompare = parseAsDate(onOrAfter, format, locale); if (!isSameOrAfter(date, onOrAfterCompare)) { return validationError( 'onOrAfter', value, Object.assign({}, options, { onOrAfter: parseDateError(onOrAfterCompare, errorFormat, locale), }) ); } } return true; } /** * This is a forcing function. If `format` provided, date and comparison date will be in String format. Otherwise, instances of Date. * I don't think there is a need to force iso8601 strings. * @function parseDate * @param {Date|String} date * @param {Object} format - { dateStyle: 'long' } or { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } * If you need to obtain precision (just compare years), use { year: 'numeric' }. * @param {String} locale * @returns {Date|String} */ export function parseDate(date, format, locale) { if (format) { // new Date("2015") will give the last day in 2014. This is problematic let yearOnly = isYearFormat(format); if (!(date instanceof Date)) { // format date into string // we have already checked this a valid date let d = yearOnly ? new Date(date, 0) : new Date(date); return new Intl.DateTimeFormat(locale, format).format(d); } // format date into string let d = yearOnly ? new Date(date.getFullYear(), 0) : date; return new Intl.DateTimeFormat(locale, format).format(d); } else { // Date constructor accepts a variety of formats including properly represented strings and Date instances. // However, a variety of formats return an "Invalid Date" literal including DD/MM/YYYY return new Date(date); } } function parseDateError(date, format, locale) { return parseDate(date, format, locale); } function parseAsDate(date, format, locale) { if (format && isYearFormat(format)) { return new Date(parseDate(date, format, locale), 0); } return new Date(parseDate(date, format, locale)); } function isValidDate(d) { return d instanceof Date && !isNaN(d); } function isSame(date, comp) { return date.getTime() === comp.getTime(); } function isBefore(date, comp) { return date < comp; } function isAfter(date, comp) { return date > comp; } function isSameOrAfter(date, comp) { return isSame(date, comp) || isAfter(date, comp); } function isSameOrBefore(date, comp) { return isSame(date, comp) || isBefore(date, comp); } function isYearFormat(format) { return Object.keys(format).length === 1 && format.year; }