Last active
May 21, 2024 08:36
-
-
Save fedeghe/041d874ef445bfeed242704153de6095 to your computer and use it in GitHub Desktop.
date format validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const testone = require('@fedeghe/testone'); | |
const validDate = value => { | |
const plainValue = value.replace(/[^\d]/g, ' '); | |
const elements = plainValue.split(/\s/).map(i => parseInt(i, 10)); | |
// must find month < 13 | |
const foundMonth = elements.findIndex(e => e > 0 && e < 13); | |
if (foundMonth < 0) return false; | |
// must find another value in [1,31] | |
const foundDate = elements.findIndex( | |
(e,i) => i != foundMonth && e > 0 && e < 32 | |
); | |
if (foundDate < 0) return false; | |
// finally must find a YYYY | |
const foundYear = elements.findIndex(e => e >= 1e3 && e < 1e4); | |
if (foundYear < 0) return false; | |
// still the date could be invalid (non leap e.g.) 2011-02-31 | |
const d = new Date(plainValue), | |
t = d.setHours(0); | |
d.setMinutes(0); | |
d.setSeconds(0); | |
d.setMilliseconds(0); | |
return d.getFullYear() === elements[foundYear] && | |
d.getMonth()+1 === elements[foundMonth] && | |
d.getDate() === elements[foundDate]; | |
}; | |
testone([ | |
{ in: ['2020-12-12'], out: true}, | |
{ in: ['2020-12-31'], out: true}, | |
{ in: ['2023-01-01'], out: true}, | |
// | |
{ in: ['2020-12-32'], out: false}, | |
{ in: ['2020-13-13'], out: false}, | |
{ in: ['2020-13-13'], out: false}, | |
{ in: ['2020-00-13'], out: false}, | |
{ in: ['999-12-13'], out: false}, | |
{ in: ['10000-12-13'], out: false}, | |
{ in: ['0-12-13'], out: false}, | |
], validDate).then(res => { | |
console.log({validDate: res.passing}) | |
}) | |
const validFormat = (format, allowedSep, els = ['YYYY', 'MM', 'DD']) => { | |
const hasEls = els.every(el => format.includes(el)), | |
sep = format.replace(/\w/g, '').split(''); | |
let sepOk = true; | |
if (allowedSep) sep.forEach(s => { | |
sepOk &&= allowedSep.includes(s); | |
}); | |
return sepOk && sep.length === els.length-1 && | |
!!hasEls; | |
}; | |
testone([ | |
{ in: ['YYYY-MM-DD'], out: true}, | |
{ in: ['YYYY-MM-DD', ['-']], out: true}, | |
{ in: ['MM-DD', ['-'], ['MM', 'DD']], out: true}, | |
{ in: ['YYYY/DD', ['/'], ['YYYY', 'DD']], out: true}, | |
// | |
{ in: ['YYYY-MM-DD', [';']], out: false}, | |
{ in: ['2020-13-13'], out: false}, | |
{ in: ['MM/DD', ['-'], ['MM', 'DD']], out: false}, | |
], validFormat).then(res => { | |
console.log({validFormat: res.passing}) | |
}); | |
function isValidDate(dateString, format, separators, placeholders) { | |
// Escape special characters in a string for use in a regex | |
function escapeRegex(str) { | |
return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | |
} | |
// Create a regex pattern to match the date format | |
let separatorPattern = separators.map(escapeRegex).join('|'); | |
let placeholderPattern = placeholders.map(escapeRegex).join('|'); | |
// Split the format into components | |
let formatComponents = format.split(new RegExp(`(${separatorPattern}|${placeholderPattern})`)); | |
// Build the regex pattern based on the format components | |
let regexPattern = formatComponents.map(component => { | |
switch (component) { | |
case 'DD': | |
return '(\\d{2})'; | |
case 'MM': | |
return '(\\d{2})'; | |
case 'YYYY': | |
return '(\\d{4})'; | |
case 'YY': | |
return '(\\d{2})'; | |
default: | |
return escapeRegex(component); | |
} | |
}).join(''); | |
let dateRegex = new RegExp(`^${regexPattern}$`); | |
let match = dateString.match(dateRegex); | |
if (!match) { | |
return false; | |
} | |
// Extract the date components from the match | |
let dateComponents = {}; | |
let formatIndex = 1; | |
formatComponents.forEach(component => { | |
if (component === 'DD' || component === 'MM' || component === 'YYYY' || component === 'YY') { | |
dateComponents[component] = match[formatIndex++]; | |
} | |
}); | |
let day = parseInt(dateComponents['DD'], 10); | |
let month = parseInt(dateComponents['MM'], 10) - 1; // Months are zero-indexed in JavaScript Date | |
let year = parseInt(dateComponents['YYYY'] || `20${dateComponents['YY']}`, 10); | |
// Validate the date by creating a Date object and checking its components | |
let date = new Date(year, month, day); | |
return date.getFullYear() === year && date.getMonth() === month && date.getDate() === day; | |
} | |
// Example usage: | |
let dateString = "12-05-2024"; | |
let format = "DD-MM-YYYY"; | |
let separators = ['-', '/']; | |
let placeholders = [' ']; | |
console.log(isValidDate(dateString, format, separators, placeholders)); // Output: true | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment