""" Tests for src/analyzer/utils/dates.py Tests cover: - parse_date(): parsing common date formats - format_date(): formatting dates for display """ import pytest from datetime import datetime from src.analyzer.utils.dates import parse_date, format_date class TestParseDate: """Test parse_date() function for flexible date parsing.""" def test_parse_date_iso_with_time(self): result = parse_date("2024-12-31T23:59:59") assert result == datetime(2024, 12, 31, 23, 59, 59) def test_parse_date_iso_date_only(self): result = parse_date("2024-12-31") assert result == datetime(2024, 12, 31) def test_parse_date_uk_format(self): result = parse_date("31/12/2024") assert result == datetime(2024, 12, 31) def test_parse_date_already_datetime(self): dt = datetime(2024, 12, 31) result = parse_date(dt) assert result == dt def test_parse_date_none(self): assert parse_date(None) is None def test_parse_date_empty_string(self): assert parse_date("") is None def test_parse_date_invalid(self): assert parse_date("not a date") is None def test_parse_date_partial_iso(self): # Should handle truncated ISO format result = parse_date("2024-12-31T23:59:59.123456") assert result == datetime(2024, 12, 31, 23, 59, 59) def test_parse_date_with_timezone(self): # Should parse up to the format length result = parse_date("2024-12-31T23:59:59Z") assert result == datetime(2024, 12, 31, 23, 59, 59) class TestFormatDate: """Test format_date() function for date formatting.""" def test_format_date_date_only(self): result = format_date("2024-12-31") assert result == "2024-12-31" def test_format_date_with_time(self): result = format_date("2024-12-31T14:30:00") assert result == "2024-12-31 14:30:00" def test_format_date_midnight(self): # Midnight (00:00:00) should show date only result = format_date("2024-12-31T00:00:00") assert result == "2024-12-31" def test_format_date_explicit_include_time(self): result = format_date("2024-12-31", include_time=True) assert result == "2024-12-31 00:00:00" def test_format_date_none(self): result = format_date(None) assert result == "—" def test_format_date_empty_string(self): result = format_date("") assert result == "—" def test_format_date_invalid(self): result = format_date("not a date") assert result == "not a date" def test_format_date_datetime_object(self): dt = datetime(2024, 12, 31, 14, 30, 0) result = format_date(dt) assert result == "2024-12-31 14:30:00" def test_format_date_uk_format_input(self): result = format_date("31/12/2024") assert result == "2024-12-31" class TestDateRoundTrip: """Test parsing and formatting work together correctly.""" def test_roundtrip_date_only(self): original = "2024-12-31" parsed = parse_date(original) formatted = format_date(parsed) assert formatted == original def test_roundtrip_with_time(self): original = "2024-12-31T14:30:00" parsed = parse_date(original) formatted = format_date(parsed) assert formatted == "2024-12-31 14:30:00" def test_roundtrip_uk_format(self): original = "31/12/2024" parsed = parse_date(original) formatted = format_date(parsed) # UK format should convert to ISO format assert formatted == "2024-12-31" class TestEdgeCases: """Test edge cases and corner scenarios.""" def test_parse_date_leap_year(self): result = parse_date("2024-02-29") assert result == datetime(2024, 2, 29) def test_parse_date_year_boundaries(self): # Test year start and end assert parse_date("2024-01-01") == datetime(2024, 1, 1) assert parse_date("2024-12-31") == datetime(2024, 12, 31) def test_format_date_preserves_seconds(self): result = format_date("2024-12-31T23:59:59") assert "59:59" in result def test_parse_date_with_extra_text(self): # Should handle ISO string with extra characters after result = parse_date("2024-12-31 (deadline)") # First 10 chars match date format assert result == datetime(2024, 12, 31) def test_format_date_with_microseconds(self): # Datetime with microseconds should format cleanly dt = datetime(2024, 12, 31, 14, 30, 0, 123456) result = format_date(dt) assert result == "2024-12-31 14:30:00" class TestIntegrationWithChatTools: """Test compatibility with existing chat_tools.py usage.""" def test_deadline_sorting_compatible(self): """Ensure parse_date works for deadline sorting logic.""" dates = [ "2024-12-31", "2024-01-15", "2024-06-30", None, "", ] # Should be able to parse all dates for sorting parsed = [parse_date(d) for d in dates] # None values should be handled assert parsed[-2] is None assert parsed[-1] is None # Valid dates should be in order valid_dates = [p for p in parsed if p is not None] assert len(valid_dates) == 3 def test_format_date_for_display(self): """Ensure format_date produces user-friendly output.""" # Common patterns from grant data test_cases = [ ("2024-12-31", "2024-12-31"), ("2024-12-31T23:59:59", "2024-12-31 23:59:59"), (None, "—"), ("", "—"), ] for input_val, expected in test_cases: result = format_date(input_val) assert result == expected if __name__ == "__main__": pytest.main([__file__, "-v"])