File size: 5,930 Bytes
bfcc872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
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"])