Skip to content

Instantly share code, notes, and snippets.

@fedeghe
Last active May 21, 2024 08:36
Show Gist options
  • Save fedeghe/041d874ef445bfeed242704153de6095 to your computer and use it in GitHub Desktop.
Save fedeghe/041d874ef445bfeed242704153de6095 to your computer and use it in GitHub Desktop.
date format validation
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