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

2 Answers

0 votes
from datetime import datetime

lst = [
    "24 Jun 2020", "25 Dec 2019", "26 Jul 2019",
    "20 Jan 2020", "27 Oct 2019", "31 Dec 2018"
]

# Sort by parsed datetime
lst.sort(key=lambda s: datetime.strptime(s, "%d %b %Y"))

# Print results
for date in lst:
    print(date)


'''
run:

31 Dec 2018
26 Jul 2019
27 Oct 2019
25 Dec 2019
20 Jan 2020
24 Jun 2020

'''

 



answered Feb 14, 2020 by avibootz
edited Sep 22 by avibootz
0 votes
"""
Sorting string dates in Python using the standard library.

This program demonstrates:
- Converting string dates into datetime objects
- Safely handling parsing errors
- Sorting using built-in functions
- Modular design with clear responsibilities
- Multiple test cases, including edge cases
- Notes on performance, memory, and pitfalls
"""

from datetime import datetime
from typing import List, Tuple


# ------------------------------------------------------------
# Core parsing function
# ------------------------------------------------------------
def parse_date(date_str: str, fmt: str) -> Tuple[datetime, str]:
    """
    Convert a date string into a datetime object using the given format.

    Returns:
        (parsed_datetime, original_string)

    The original string is returned so that the caller can preserve
    the original representation if needed.

    Error handling:
        - If parsing fails, we raise ValueError with a clear message.
        - This allows the caller to decide how to handle invalid input.

    Security note:
        - Using datetime.strptime is safe for user input; it does not
          execute arbitrary code and only interprets structured date formats.

    Performance:
        - O(1) per parse; overall O(n) for n dates.
    """
    try:
        return datetime.strptime(date_str, fmt), date_str
    except ValueError as exc:
        raise ValueError(f"Invalid date '{date_str}' for format '{fmt}'") from exc


# ------------------------------------------------------------
# Sorting function
# ------------------------------------------------------------
def sort_dates(date_strings: List[str], fmt: str) -> List[str]:
    """
    Sort a list of date strings according to the given format.

    Steps:
        1. Parse each date string into a datetime object.
        2. Sort the parsed results by the datetime value.
        3. Return the original strings in sorted order.

    Complexity:
        - Parsing: O(n)
        - Sorting: O(n log n)
        - Total: O(n log n)

    Pitfalls:
        - Mixed formats in the input will cause parsing errors.
        - Leading/trailing whitespace should be stripped by the caller if needed.
        - Timezone-aware strings require different parsing logic.

    Memory:
        - Temporary list of parsed dates is proportional to input size.
    """
    parsed = []
    for ds in date_strings:
        parsed.append(parse_date(ds, fmt))

    # Sort by the datetime object (index 0 of tuple)
    parsed.sort(key=lambda item: item[0])

    # Return the original strings in sorted order
    return [orig for _, orig in parsed]


# ------------------------------------------------------------
# Test harness
# ------------------------------------------------------------
def run_test_case(name: str, dates: List[str], fmt: str) -> None:
    """
    Run a single test case and print results.

    Includes:
        - Clear labeling
        - Error handling
        - Edge case demonstration
    """
    print(f"\nTest case: {name}")
    print("Input:", dates)
    try:
        result = sort_dates(dates, fmt)
        print("Sorted:", result)
    except ValueError as err:
        print("Error:", err)


# ------------------------------------------------------------
# Main entry point
# ------------------------------------------------------------
def main() -> None:
    """
    Demonstrates multiple test cases, including:
        - Normal dates
        - Already sorted dates
        - Reverse-sorted dates
        - Duplicate dates
        - Invalid dates (error handling)
        - Edge cases (empty list)
    """

    # Common format for tests
    fmt = "%Y-%m-%d"

    # Normal case
    run_test_case(
        name="Normal case",
        dates=["2024-01-05", "2023-12-31", "2024-01-01"],
        fmt=fmt,
    )

    # Already sorted
    run_test_case(
        name="Already sorted",
        dates=["2023-01-01", "2023-02-01", "2023-03-01"],
        fmt=fmt,
    )

    # Reverse sorted
    run_test_case(
        name="Reverse sorted",
        dates=["2024-12-31", "2024-06-01", "2024-01-01"],
        fmt=fmt,
    )

    # Duplicate dates
    run_test_case(
        name="Duplicates",
        dates=["2024-01-01", "2024-01-01", "2023-12-31"],
        fmt=fmt,
    )

    # Invalid date
    run_test_case(
        name="Invalid date",
        dates=["2024-01-01", "not-a-date", "2024-02-01"],
        fmt=fmt,
    )

    # Empty list
    run_test_case(
        name="Empty list",
        dates=[],
        fmt=fmt,
    )


if __name__ == "__main__":
    main()


"""
run:

Test case: Normal case
Input: ['2024-01-05', '2023-12-31', '2024-01-01']
Sorted: ['2023-12-31', '2024-01-01', '2024-01-05']

Test case: Already sorted
Input: ['2023-01-01', '2023-02-01', '2023-03-01']
ERROR!
Sorted: ['2023-01-01', '2023-02-01', '2023-03-01']

Test case: Reverse sorted
Input: ['2024-12-31', '2024-06-01', '2024-01-01']
Sorted: ['2024-01-01', '2024-06-01', '2024-12-31']

Test case: Duplicates
Input: ['2024-01-01', '2024-01-01', '2023-12-31']
Sorted: ['2023-12-31', '2024-01-01', '2024-01-01']

Test case: Invalid date
Input: ['2024-01-01', 'not-a-date', '2024-02-01']
Error: Invalid date 'not-a-date' for format '%Y-%m-%d'

Test case: Empty list
Input: []
Sorted: []

"""

 



answered Sep 22 by avibootz
...