/**
* Compare two dates in JavaScript
* -------------------------------
* This program demonstrates how to compare two dates using the built‑in
* Date object. It uses a modular design, clear comments, and a full test suite.
*
* Concepts:
* - Parsing dates safely
* - Comparing Date objects
* - Handling invalid formats
* - Edge‑case testing
*
* Architecture notes:
* - A dedicated function handles parsing.
* - Another function performs comparison.
* - Main runs multiple predefined test cases.
* - No external dependencies; only standard library.
*
* Performance notes:
* - Date comparisons are O(1).
* - Parsing is fast and predictable.
* - Memory usage is minimal.
*
* Pitfalls:
* - Invalid date strings produce "Invalid Date".
* - Comparing raw strings is unsafe; always convert to Date objects.
* - Timezones matter: Date() defaults to local timezone.
* For strict date‑only comparison, normalize to midnight UTC.
*
*/
/**
* Safely parse a date string into a Date object.
*
* Supported format: YYYY-MM-DD
*
* Error handling:
* - Returns null if the date is invalid.
* - Avoids throwing exceptions in the test loop.
*/
function parseDate(dateStr) {
// Normalize to midnight UTC to avoid timezone shifts
const d = new Date(dateStr + "T00:00:00Z");
// Check for invalid date
if (isNaN(d.getTime())) {
return null;
}
return d;
}
/**
* Compare two Date objects.
*
* Returns:
* - "earlier"
* - "later"
* - "equal"
*/
function compareDates(d1, d2) {
if (d1 < d2) return "earlier";
if (d1 > d2) return "later";
return "equal";
}
/**
* Run a single test case:
* - Parse both dates
* - Handle invalid input
* - Compare if valid
*/
function runTestCase(date1, date2) {
const d1 = parseDate(date1);
const d2 = parseDate(date2);
if (!d1 || !d2) {
return { date1, date2, result: "invalid date format" };
}
return { date1, date2, result: compareDates(d1, d2) };
}
/**
* Main test suite:
* - Multiple test cases
* - Includes edge cases
* - Prints results cleanly
*/
function main() {
const tests = [
["2024-01-01", "2024-01-02"], // earlier
["2024-01-02", "2024-01-01"], // later
["2024-01-01", "2024-01-01"], // equal
["1999-12-31", "2000-01-01"], // millennium boundary
["2024-02-29", "2024-03-01"], // leap year
["2024-02-29", "2023-02-28"], // leap vs non-leap
["2024-13-01", "2024-01-01"], // invalid month
["2024-00-10", "2024-01-01"], // invalid month
["2024-01-32", "2024-01-01"], // invalid day
["abcd-ef-gh", "2024-01-01"], // invalid format
["2024-01-01", "abcd-ef-gh"], // invalid format
];
console.log("Date comparison tests:\n");
for (const [d1, d2] of tests) {
const { date1, date2, result } = runTestCase(d1, d2);
console.log(`Compare '${date1}' vs '${date2}' → ${result}`);
}
}
main();
/*
run:
Date comparison tests:
Compare '2024-01-01' vs '2024-01-02' → earlier
Compare '2024-01-02' vs '2024-01-01' → later
Compare '2024-01-01' vs '2024-01-01' → equal
Compare '1999-12-31' vs '2000-01-01' → earlier
Compare '2024-02-29' vs '2024-03-01' → earlier
Compare '2024-02-29' vs '2023-02-28' → later
Compare '2024-13-01' vs '2024-01-01' → invalid date format
Compare '2024-00-10' vs '2024-01-01' → invalid date format
Compare '2024-01-32' vs '2024-01-01' → invalid date format
Compare 'abcd-ef-gh' vs '2024-01-01' → invalid date format
Compare '2024-01-01' vs 'abcd-ef-gh' → invalid date format
*/