# Compare two dates in Ruby
# -------------------------
# This program demonstrates how to compare two dates using Ruby’s built‑in
# Date class from the standard library. It uses a modular design, clear comments,
# and a full test suite.
#
# Concepts:
# - Parsing dates safely (YYYY‑MM‑DD)
# - 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 must be handled.
# - Comparing raw strings is unsafe; always convert to Date.
# - Date is date‑only; no timezone concerns here.
require "date"
# Safely parse a date string in the format YYYY-MM-DD.
# Returns nil if the date is invalid.
def parse_date(str)
Date.strptime(str, "%Y-%m-%d")
rescue ArgumentError
nil
end
# Compare two Date objects.
# Returns: "earlier", "later", or "equal".
def compare_dates(a, b)
return "earlier" if a < b
return "later" if a > b
"equal"
end
# Run a single test case:
# - Parse both dates
# - Handle invalid input
# - Compare if valid
def run_test_case(d1, d2)
a = parse_date(d1)
b = parse_date(d2)
if a.nil? || b.nil?
puts "Compare '#{d1}' vs '#{d2}' → invalid date format"
return
end
puts "Compare '#{d1}' vs '#{d2}' → #{compare_dates(a, b)}"
end
# Main test suite:
# - Multiple test cases
# - Includes edge cases
# - Prints results cleanly
def main
puts "Date comparison tests:\n\n"
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
]
tests.each { |d1, d2| run_test_case(d1, d2) }
end
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
#