Skip to content

Commit

Permalink
Add format argument to parse_*
Browse files Browse the repository at this point in the history
``parse_date()`` does not allow the user to specify the date's format
and the 'medium' format is used by default in the call to
``get_date_format()`` on line 1144.

This results in a failure to parse the date in short format for the
locale 'sv_SE'. This commit adds the format argument to avoid this
failure. The default value is set to 'medium' to preserve the old behavior.

Fixes #657

Co-authored-by: Aarni Koskela <akx@iki.fi>
  • Loading branch information
j4321 and akx committed Jan 27, 2022
1 parent f420e96 commit d9246f4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 13 deletions.
28 changes: 15 additions & 13 deletions babel/dates.py
Expand Up @@ -1142,7 +1142,7 @@ class ParseError(ValueError):
pass


def parse_date(string, locale=LC_TIME):
def parse_date(string, locale=LC_TIME, format='medium'):
"""Parse a date from a string.
This function uses the date format for the locale as a hint to determine
Expand All @@ -1155,18 +1155,19 @@ def parse_date(string, locale=LC_TIME):
:param string: the string containing the date
:param locale: a `Locale` object or a locale identifier
:param format: the format to use (see ``get_date_format``)
"""
numbers = re.findall(r'(\d+)', string)
if not numbers:
raise ParseError("No numbers were found in input")

# TODO: try ISO format first?
format = get_date_format(locale=locale).pattern.lower()
year_idx = format.index('y')
month_idx = format.index('m')
format_str = get_date_format(format=format, locale=locale).pattern.lower()
year_idx = format_str.index('y')
month_idx = format_str.index('m')
if month_idx < 0:
month_idx = format.index('l')
day_idx = format.index('d')
month_idx = format_str.index('l')
day_idx = format_str.index('d')

indexes = [(year_idx, 'Y'), (month_idx, 'M'), (day_idx, 'D')]
indexes.sort()
Expand All @@ -1187,7 +1188,7 @@ def parse_date(string, locale=LC_TIME):
return date(year, month, day)


def parse_time(string, locale=LC_TIME):
def parse_time(string, locale=LC_TIME, format='medium'):
"""Parse a time from a string.
This function uses the time format for the locale as a hint to determine
Expand All @@ -1198,6 +1199,7 @@ def parse_time(string, locale=LC_TIME):
:param string: the string containing the time
:param locale: a `Locale` object or a locale identifier
:param format: the format to use (see ``get_time_format``)
:return: the parsed time
:rtype: `time`
"""
Expand All @@ -1206,12 +1208,12 @@ def parse_time(string, locale=LC_TIME):
raise ParseError("No numbers were found in input")

# TODO: try ISO format first?
format = get_time_format(locale=locale).pattern.lower()
hour_idx = format.index('h')
format_str = get_time_format(format=format, locale=locale).pattern.lower()
hour_idx = format_str.index('h')
if hour_idx < 0:
hour_idx = format.index('k')
min_idx = format.index('m')
sec_idx = format.index('s')
hour_idx = format_str.index('k')
min_idx = format_str.index('m')
sec_idx = format_str.index('s')

indexes = [(hour_idx, 'H'), (min_idx, 'M'), (sec_idx, 'S')]
indexes.sort()
Expand All @@ -1222,7 +1224,7 @@ def parse_time(string, locale=LC_TIME):
# 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 'a' in format_str:
if 'pm' in string.lower():
hour_offset = 12

Expand Down
1 change: 1 addition & 0 deletions tests/test_dates.py
Expand Up @@ -775,6 +775,7 @@ def test_format_timedelta():
def test_parse_date():
assert dates.parse_date('4/1/04', locale='en_US') == date(2004, 4, 1)
assert dates.parse_date('01.04.2004', locale='de_DE') == date(2004, 4, 1)
assert dates.parse_date('2004-04-01', locale='sv_SE', format='short') == date(2004, 4, 1)


@pytest.mark.parametrize('input, expected', [
Expand Down

0 comments on commit d9246f4

Please sign in to comment.