UNPKG

ajt-validator

Version:

Validation library for JavaScript and TypeScript

196 lines (195 loc) 7.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DOBValidator = void 0; const base_1 = require("../base"); /** * Validator for Date of Birth fields * Validates dates and provides age calculations */ class DOBValidator extends base_1.BaseValidator { /** * Create a new Date of Birth validator * @param options Configuration options for DOB validation */ constructor(options = {}) { super(); this.DEFAULT_MIN_AGE = 0; this.DEFAULT_MAX_AGE = 120; this.options = Object.assign({ minAge: this.DEFAULT_MIN_AGE, maxAge: this.DEFAULT_MAX_AGE, allowFutureDates: false }, options); } /** * Validate a date of birth value * @param value DOB as string or Date object * @returns Validation result with additional DOB and age metadata */ validate(value) { // Handle null/undefined if (value === null || value === undefined) { return this.createError('DOB_REQUIRED', 'Date of birth is required'); } // Parse the date if it's a string let dateObj; if (typeof value === 'string') { dateObj = this.parseDate(value); if (isNaN(dateObj.getTime())) { return this.createError('INVALID_DATE_FORMAT', 'Invalid date format'); } } else if (value instanceof Date) { dateObj = value; // Validate that it's a valid date if (isNaN(dateObj.getTime())) { return this.createError('INVALID_DATE', 'Invalid date'); } } else { return this.createError('INVALID_INPUT_TYPE', 'Date of birth must be a string or Date object'); } // Get reference date (today by default) const referenceDate = this.options.referenceDate || new Date(); // Check for future dates if (!this.options.allowFutureDates && dateObj > referenceDate) { return this.createError('FUTURE_DATE', 'Date of birth cannot be in the future'); } // Calculate age const age = this.calculateAge(dateObj, referenceDate); // Validate minimum age if (age.years < this.options.minAge) { return this.createError('BELOW_MINIMUM_AGE', `Age must be at least ${this.options.minAge} years`); } // Validate maximum age if (age.years > this.options.maxAge) { return this.createError('ABOVE_MAXIMUM_AGE', `Age must not exceed ${this.options.maxAge} years`); } // Check if DOB falls within any specified valid ranges let category; if (this.options.validRanges && this.options.validRanges.length > 0) { const matchingRange = this.options.validRanges.find(range => dateObj >= range.startDate && dateObj <= range.endDate); category = matchingRange === null || matchingRange === void 0 ? void 0 : matchingRange.name; // If valid ranges are specified and DOB doesn't match any, it's invalid if (!matchingRange) { return this.createError('OUTSIDE_VALID_RANGES', 'Date of birth does not fall within any valid range'); } } // Return successful validation result with metadata return { isValid: true, value: dateObj, age, category, isLegalAge: age.years >= this.options.minAge }; } /** * Check if a person is of legal age based on their DOB * @param dob Date of birth * @param minAge Minimum age to be considered legal (defaults to options.minAge) * @returns Whether the person is of legal age */ isLegalAge(dob, minAge) { const minimumAge = minAge || this.options.minAge || 18; // Default to 18 if not specified const age = this.calculateAge(dob).years; return age >= minimumAge; } /** * Get age at a specific reference date * @param dob Date of birth * @param referenceDate Date to calculate age at (defaults to current date) * @returns Age details */ getAgeAt(dob, referenceDate) { return this.calculateAge(dob, referenceDate); } /** * Calculate exact age from DOB * @param dob Date of birth * @param referenceDate Reference date (defaults to current date) * @returns Detailed age calculation */ calculateAge(dob, referenceDate = new Date()) { let years = referenceDate.getFullYear() - dob.getFullYear(); let months = referenceDate.getMonth() - dob.getMonth(); let days = referenceDate.getDate() - dob.getDate(); // Adjust for negative days if (days < 0) { // Get the number of days in the previous month const previousMonth = new Date(referenceDate.getFullYear(), referenceDate.getMonth(), 0).getDate(); days += previousMonth; months--; } // Adjust for negative months if (months < 0) { years--; months += 12; } // Calculate decimal years (approximate) const daysInYear = 365.25; // Account for leap years const decimalYears = years + (months / 12) + (days / daysInYear); return { years, months, days, decimalYears: Math.round(decimalYears * 100) / 100 // Round to 2 decimal places }; } /** * Parse string date into Date object with format detection * @param dateStr Date string * @returns Parsed Date object */ parseDate(dateStr) { var _a; // Try to parse with Date constructor first const date = new Date(dateStr); if (!isNaN(date.getTime())) { return date; } // If strict format validation is enabled, check against allowed formats if (((_a = this.options.format) === null || _a === void 0 ? void 0 : _a.strict) && this.options.format.allowedFormats) { // Implementation would check each allowed format // This is simplified - in a real implementation you would need // to check each format pattern (perhaps using a library like date-fns) } // Common formats handling // MM/DD/YYYY const usFormat = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/; const usMatch = dateStr.match(usFormat); if (usMatch) { return new Date(parseInt(usMatch[3]), // year parseInt(usMatch[1]) - 1, // month (0-based) parseInt(usMatch[2]) // day ); } // DD/MM/YYYY const ukFormat = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/; const ukMatch = dateStr.match(ukFormat); if (ukMatch) { return new Date(parseInt(ukMatch[3]), // year parseInt(ukMatch[2]) - 1, // month (0-based) parseInt(ukMatch[1]) // day ); } // YYYY-MM-DD (ISO format) const isoFormat = /^(\d{4})-(\d{1,2})-(\d{1,2})$/; const isoMatch = dateStr.match(isoFormat); if (isoMatch) { return new Date(parseInt(isoMatch[1]), // year parseInt(isoMatch[2]) - 1, // month (0-based) parseInt(isoMatch[3]) // day ); } // If no format matched, return invalid date return new Date('Invalid Date'); } /** * Create an error result for DOB validation */ createError(code, message) { return { isValid: false, errors: [{ code, message }], age: undefined }; } } exports.DOBValidator = DOBValidator;