UNPKG

redux-form-validators

Version:

Simple validations with redux-form / react-final-form

171 lines (155 loc) 4.96 kB
import Validators from './validators' import { prepareMsg, prepare, trunc, memoize, assign } from './helpers' const DATE_METHODS = { y: function (d) { return d.getFullYear() }, m: function (d) { return d.getMonth() + 1 }, d: function (d) { return d.getDate() } } const PARSE_REG = /(y+|m+|d+)/g const TO_STRING = {}.toString let date = memoize(function ({ format, ymd, '=': eq, '!=': diff, '>': gt, '>=': gte, '<': lt, '<=': lte, message, msg, if: ifCond, unless, allowBlank } = {}) { msg = msg || message return prepare(ifCond, unless, allowBlank, function (value) { let normFormat = normalizeFormat(format, ymd) let date = normParseDate(value, normFormat, false) if (date === 'wrongFormat') { return Validators.formatMessage(prepareMsg(msg, 'dateFormat', 'format', { format: format })) } if (date === 'invalid') { return Validators.formatMessage(prepareMsg(msg, 'dateInvalid', 'invalid')) } if (date) { let date2 if (eq && +date !== +(date2 = getDate(eq))) { return Validators.formatMessage(prepareMsg(msg, 'dateRange', 'range', '=', values('=', date2, normFormat))) } if (diff && +date === +(date2 = getDate(diff))) { return Validators.formatMessage(prepareMsg(msg, 'dateRange', 'range', '!=', values('!=', date2, normFormat))) } if (gt && date <= (date2 = getDate(gt))) { return Validators.formatMessage(prepareMsg(msg, 'dateRange', 'range', '>', values('>', date2, normFormat))) } if (gte && date < (date2 = getDate(gte))) { return Validators.formatMessage(prepareMsg(msg, 'dateRange', 'range', '>=', values('>=', date2, normFormat))) } if (lt && date >= (date2 = getDate(lt))) { return Validators.formatMessage(prepareMsg(msg, 'dateRange', 'range', '<', values('<', date2, normFormat))) } if (lte && date > (date2 = getDate(lte))) { return Validators.formatMessage(prepareMsg(msg, 'dateRange', 'range', '<=', values('<=', date2, normFormat))) } } }) }) date.parseDate = parseDate date.formatDate = formatDate export default date function parseDate (strDate, format, ymd) { return normParseDate(strDate, normalizeFormat(format, ymd), true) } function formatDate (date, format, ymd) { if (!(date instanceof Date) && TO_STRING.call(date) !== '[object Date]') { return null } let t = new Date(date).getTime() // eslint-disable-next-line no-self-compare return t !== t ? null : normFormatDate(date, normalizeFormat(format, ymd)) } function values (op, date, format) { return { op: op, date: normFormatDate(date, format), dateObject: date } } function getDate (d) { if (typeof d === 'function') { return new Date(+d()) } if (isNaN(d) && ('' + d).toLowerCase() === 'today') { let today = new Date() today.setHours(0, 0, 0, 0) return today } return new Date(+d) } // FORMAT function normFormatDate (date, format) { return format.replace(PARSE_REG, function (m) { let sym = m.charAt(0) let len = m.length let padded = padding(DATE_METHODS[sym](date), len) return sym === 'y' ? padded.slice(padded.length - len, padded.length) : padded }) } function normalizeFormat (format, ymd) { if (format == null) { format = Validators.defaultOptions.dateFormat } if (!ymd) { ymd = Validators.defaultOptions.dateYmd } if (!ymd || ymd === 'ymd') { return format } let reverseMapping = {} reverseMapping[ymd.charAt(0)] = 'y' reverseMapping[ymd.charAt(1)] = 'm' reverseMapping[ymd.charAt(2)] = 'd' return format.replace(new RegExp(`[${ymd}]`, 'g'), function (sym) { return reverseMapping[sym] }) } function padding (num, pad) { return '0'.repeat(Math.max(0, pad - ('' + num).length)) + num } // PARSE function normParseDate (value, format, parse) { let order = [] let reg = new RegExp( '^' + format.replace(PARSE_REG, function (m) { order.push(m.charAt(0)) return `([0-9]{${m.length}})` }) + '$' ) let match = value.match(reg) if (match) { let flags = {} order.forEach(function (token, index) { flags[token] = +match[index + 1] }) let comparable = flags.y != null ? (flags.m != null ? true : flags.d == null) : false flags = assign({ y: 1970, m: 1, d: 1 }, flags) if (flags.y < 100) { flags.y = currentCentury(flags.y >= 69 ? -1 : 0) * 100 + flags.y } let date = new Date(flags.y, flags.m - 1, flags.d) return checkFlags(date, flags) ? (comparable || parse ? date : null) : parse ? new Date(NaN) : 'invalid' } return parse ? new Date(NaN) : 'wrongFormat' } function checkFlags (date, flags) { let [year, month, day] = [date.getFullYear(), date.getMonth() + 1, date.getDate()] return year === flags.y && month === flags.m && day === flags.d } function currentCentury (add) { return trunc(new Date().getFullYear() / 100) + add }