File: test_approxidate.py

package info (click to toggle)
dulwich 1.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 7,388 kB
  • sloc: python: 99,991; makefile: 163; sh: 67
file content (161 lines) | stat: -rw-r--r-- 6,420 bytes parent folder | download | duplicates (2)
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
# test_approxidate.py -- tests for approxidate.py
# Copyright (C) 2025 Jelmer Vernooij <jelmer@jelmer.uk>
#
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
# General Public License as published by the Free Software Foundation; version 2.0
# or (at your option) any later version. You can redistribute it and/or
# modify it under the terms of either of these two licenses.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# You should have received a copy of the licenses; if not, see
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
# License, Version 2.0.
#

"""Tests for approxidate parsing."""

import time

from dulwich.approxidate import parse_approxidate, parse_relative_time

from . import TestCase


class ParseRelativeTimeTests(TestCase):
    """Test parse_relative_time."""

    def test_now(self) -> None:
        self.assertEqual(0, parse_relative_time("now"))

    def test_seconds_ago(self) -> None:
        self.assertEqual(5, parse_relative_time("5 seconds ago"))
        self.assertEqual(1, parse_relative_time("1 second ago"))

    def test_minutes_ago(self) -> None:
        self.assertEqual(5 * 60, parse_relative_time("5 minutes ago"))
        self.assertEqual(1 * 60, parse_relative_time("1 minute ago"))

    def test_hours_ago(self) -> None:
        self.assertEqual(5 * 3600, parse_relative_time("5 hours ago"))
        self.assertEqual(1 * 3600, parse_relative_time("1 hour ago"))

    def test_days_ago(self) -> None:
        self.assertEqual(5 * 86400, parse_relative_time("5 days ago"))
        self.assertEqual(1 * 86400, parse_relative_time("1 day ago"))

    def test_weeks_ago(self) -> None:
        self.assertEqual(2 * 604800, parse_relative_time("2 weeks ago"))
        self.assertEqual(1 * 604800, parse_relative_time("1 week ago"))

    def test_months_ago(self) -> None:
        self.assertEqual(2 * 2592000, parse_relative_time("2 months ago"))
        self.assertEqual(1 * 2592000, parse_relative_time("1 month ago"))

    def test_years_ago(self) -> None:
        self.assertEqual(2 * 31536000, parse_relative_time("2 years ago"))
        self.assertEqual(1 * 31536000, parse_relative_time("1 year ago"))

    def test_dot_separated_format(self) -> None:
        # Git supports both "2 weeks ago" and "2.weeks.ago"
        self.assertEqual(2 * 604800, parse_relative_time("2.weeks.ago"))
        self.assertEqual(5 * 86400, parse_relative_time("5.days.ago"))

    def test_invalid_format(self) -> None:
        self.assertRaises(ValueError, parse_relative_time, "not a time")
        self.assertRaises(ValueError, parse_relative_time, "5 weeks")  # Missing "ago"

    def test_invalid_unit(self) -> None:
        self.assertRaises(ValueError, parse_relative_time, "5 fortnights ago")

    def test_invalid_number(self) -> None:
        self.assertRaises(ValueError, parse_relative_time, "abc weeks ago")


class ParseApproxidateTests(TestCase):
    """Test parse_approxidate."""

    def test_now(self) -> None:
        result = parse_approxidate("now")
        # Should be close to current time
        self.assertAlmostEqual(result, time.time(), delta=2)

    def test_yesterday(self) -> None:
        result = parse_approxidate("yesterday")
        expected = time.time() - 86400
        self.assertAlmostEqual(result, expected, delta=2)

    def test_today(self) -> None:
        result = parse_approxidate("today")
        # Should be midnight of current day
        from datetime import datetime

        now = datetime.fromtimestamp(time.time())
        expected_dt = now.replace(hour=0, minute=0, second=0, microsecond=0)
        expected = int(expected_dt.timestamp())
        self.assertEqual(result, expected)

    def test_unix_timestamp(self) -> None:
        self.assertEqual(1234567890, parse_approxidate("1234567890"))
        self.assertEqual(0, parse_approxidate("0"))

    def test_relative_times(self) -> None:
        # Test relative time parsing
        result = parse_approxidate("2 weeks ago")
        expected = time.time() - (2 * 604800)
        self.assertAlmostEqual(result, expected, delta=2)

        result = parse_approxidate("5.days.ago")
        expected = time.time() - (5 * 86400)
        self.assertAlmostEqual(result, expected, delta=2)

    def test_absolute_date_iso(self) -> None:
        # Test ISO format date
        result = parse_approxidate("2009-02-13")
        # 2009-02-13 00:00:00 UTC
        from datetime import datetime

        expected = int(datetime(2009, 2, 13, 0, 0, 0).timestamp())
        self.assertEqual(result, expected)

    def test_absolute_datetime_iso(self) -> None:
        # Test ISO format datetime
        result = parse_approxidate("2009-02-13 23:31:30")
        from datetime import datetime

        expected = int(datetime(2009, 2, 13, 23, 31, 30).timestamp())
        self.assertEqual(result, expected)

    def test_absolute_datetime_iso8601(self) -> None:
        # Test ISO 8601 format
        result = parse_approxidate("2009-02-13T23:31:30")
        from datetime import datetime

        expected = int(datetime(2009, 2, 13, 23, 31, 30).timestamp())
        self.assertEqual(result, expected)

    def test_bytes_input(self) -> None:
        # Test that bytes input works
        result = parse_approxidate(b"1234567890")
        self.assertEqual(1234567890, result)

        result = parse_approxidate(b"yesterday")
        expected = time.time() - 86400
        self.assertAlmostEqual(result, expected, delta=2)

    def test_whitespace_handling(self) -> None:
        # Test that leading/trailing whitespace is handled
        self.assertEqual(1234567890, parse_approxidate("  1234567890  "))
        result = parse_approxidate("  yesterday  ")
        expected = time.time() - 86400
        self.assertAlmostEqual(result, expected, delta=2)

    def test_invalid_spec(self) -> None:
        self.assertRaises(ValueError, parse_approxidate, "not a valid time")
        self.assertRaises(ValueError, parse_approxidate, "abc123")