Spaces:
Sleeping
Sleeping
| """ | |
| 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"]) | |