How to sort a list of string‑based dates in JavaScript

1 Answer

0 votes
/*
    Program goal:
    -------------
    Sort a list of date strings in the format "YYYY-MM-DD".

    Approach:
      1. Parse each string into a Date object using a safe, explicit parser.
      2. Sort using Array.prototype.sort() with a comparator.
      3. Convert back to strings and print results.

    Architecture notes:
    -------------------
    - Parsing is isolated in a dedicated function for clarity and testability.
    - Sorting uses the built-in sort() with a comparator (O(n log n)).
    - Error handling: invalid formats are detected and reported.
    - Edge cases: malformed strings, invalid ranges, leap years.
    - Performance: Date parsing is fast; sorting is O(n log n).
    - Memory: minimal; only an array of small objects.
    - Security: no unsafe operations; avoids eval-like parsing.
*/

/*
    Parse a date string into a Date object.
    Throws an error with a clear message on failure.
*/
function parseDate(s) {
    // Basic structural validation: YYYY-MM-DD
    if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) {
        throw new Error("Invalid date format: " + s);
    }

    const [year, month, day] = s.split("-").map(Number);

    // Construct a Date in UTC to avoid timezone surprises
    const dt = new Date(Date.UTC(year, month - 1, day));

    // Validate that the Date object matches the input (detects invalid calendar dates)
    if (
        dt.getUTCFullYear() !== year ||
        dt.getUTCMonth() !== month - 1 ||
        dt.getUTCDate() !== day
    ) {
        throw new Error("Invalid calendar date: " + s);
    }

    return dt;
}

/*
    Sort a list of date strings.
    Returns a new sorted array; does not mutate the input.
*/
function sortDates(dates) {
    const parsed = [];

    // Parse all dates; fail fast on invalid input.
    for (const s of dates) {
        parsed.push(parseDate(s));
    }

    // Sort using natural Date ordering.
    parsed.sort((a, b) => a - b);

    // Convert back to strings.
    return parsed.map(
        d =>
            `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, "0")}-${String(
                d.getUTCDate()
            ).padStart(2, "0")}`
    );
}

/*
    Helper to print a list of strings.
*/
function printList(list) {
    for (const s of list) {
        console.log("  " + s);
    }
}

/*
    Helper to run a named test case.
*/
function runTest(name, dates) {
    console.log("\n=== " + name + " ===");
    try {
        const sorted = sortDates(dates);
        printList(sorted);
    } catch (e) {
        console.log("Error: " + e.message);
    }
}

/*
    Main program with multiple test cases.
*/
console.log("JavaScript Date Sorting Demo");

/* Basic chronological order */
runTest("Basic chronological order", [
    "2024-01-05",
    "2023-12-31",
    "2024-01-01",
    "2022-07-15"
]);

/* Already sorted input */
runTest("Already sorted input", [
    "2020-01-01",
    "2020-01-02",
    "2020-01-03"
]);

/* Leap year edge cases */
runTest("Leap year edge cases", [
    "2020-02-29",
    "2019-02-28",
    "2021-03-01"
]);

/* Invalid date detection */
runTest("Invalid date detection", [
    "2024-13-01",   // invalid month
    "2024-02-30",   // invalid day
    "not-a-date"    // malformed
]);



/*
run:

JavaScript Date Sorting Demo

=== Basic chronological order ===
  2022-07-15
  2023-12-31
  2024-01-01
  2024-01-05

=== Already sorted input ===
  2020-01-01
  2020-01-02
  2020-01-03

=== Leap year edge cases ===
  2019-02-28
  2020-02-29
  2021-03-01

=== Invalid date detection ===
ERROR!
Error: Invalid calendar date: 2024-13-01

*/

 



answered Sep 23 by avibootz
...