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")
|