]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
Improve partial time parsing
authorAarni Koskela <akx@iki.fi>
Thu, 27 Jan 2022 15:09:39 +0000 (17:09 +0200)
committerAarni Koskela <akx@iki.fi>
Fri, 28 Jan 2022 09:07:08 +0000 (11:07 +0200)
Refs #442

Co-authored-by: David Bauer <david.bauer009@gmail.com>
Co-authored-by: Arthur Jovart <arthur@jovart.com>
babel/dates.py
tests/test_dates.py

index f94c60a0d3f8c7fc90e2b17c5d21e3b35d370aec..4c14ea2bd9106bf5acfe155fb0153948d7ca2cd4 100644 (file)
@@ -1206,14 +1206,24 @@ def parse_time(string, locale=LC_TIME):
     indexes.sort()
     indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)])
 
-    # FIXME: support 12 hour clock, and 0-based hour specification
-    #        and seconds should be optional, maybe minutes too
-    #        oh, and time-zones, of course
+    # TODO: support time zones
+
+    # Check if the format specifies a period to be used;
+    # if it does, look for 'pm' to figure out an offset.
+    hour_offset = 0
+    if 'a' in format:
+        if 'pm' in string.lower():
+            hour_offset = 12
 
     numbers = re.findall(r'(\d+)', string)
-    hour = int(numbers[indexes['H']])
-    minute = int(numbers[indexes['M']])
-    second = int(numbers[indexes['S']])
+
+    # Parse up to three numbers from the string.
+    minute = second = 0
+    hour = int(numbers[indexes['H']]) + hour_offset
+    if len(numbers) > 1:
+        minute = int(numbers[indexes['M']])
+        if len(numbers) > 2:
+            second = int(numbers[indexes['S']])
     return time(hour, minute, second)
 
 
index d11758c5bec4bf1b0432d8a9954731b80052078e..d85fd08305bbaab37841fd724a3fcf5e39d86ba5 100644 (file)
@@ -777,8 +777,27 @@ def test_parse_date():
     assert dates.parse_date('01.04.2004', locale='de_DE') == date(2004, 4, 1)
 
 
-def test_parse_time():
-    assert dates.parse_time('15:30:00', locale='en_US') == time(15, 30)
+@pytest.mark.parametrize('input, expected', [
+    # base case, fully qualified time
+    ('15:30:00', time(15, 30)),
+    # test digits
+    ('15:30', time(15, 30)),
+    ('3:30', time(3, 30)),
+    ('00:30', time(0, 30)),
+    # test am parsing
+    ('03:30 am', time(3, 30)),
+    ('3:30:21 am', time(3, 30, 21)),
+    ('3:30 am', time(3, 30)),
+    # test pm parsing
+    ('03:30 pm', time(15, 30)),
+    ('03:30 pM', time(15, 30)),
+    ('03:30 Pm', time(15, 30)),
+    ('03:30 PM', time(15, 30)),
+    # test hour-only parsing
+    ('4 pm', time(16, 0)),
+])
+def test_parse_time(input, expected):
+    assert dates.parse_time(input, locale='en_US') == expected
 
 
 def test_datetime_format_get_week_number():