Simplify date parsing (#195)

Create common functions parse_date, parse_month_year_date and parse_datetime.

Those functions support trying multiple formats, and come with default formats lists that support most of the date format encountered so far.

Notable change: year-month dates are now set to the end of month (impacted couchbase-server and ibm-aix).
This commit is contained in:
Marc Wrobel
2023-11-26 21:01:35 +01:00
committed by GitHub
parent 1e65a048b0
commit 0d17306872
24 changed files with 133 additions and 168 deletions

51
src/common/dates.py Normal file
View File

@@ -0,0 +1,51 @@
from datetime import datetime, timezone
import calendar
def parse_date(text, formats=frozenset([
"%B %d, %Y", # January 1, 2020
"%b %d, %Y", # Jan 1, 2020
"%B %d %Y", # January 1 2020
"%b %d %Y", # Jan 1 2020
"%d %B %Y", # 1 January 2020
"%d %b %Y", # 1 Jan 2020
"%d-%b-%Y", # 1-Jan-2020
"%d-%B-%Y", # 1-January-2020
])) -> datetime:
"""Parse a given text representing a date using a list of formats.
"""
return parse_datetime(text, formats, to_utc=False)
def parse_month_year_date(text, formats=frozenset([
"%B %Y", # January 2020
"%b %Y", # Jan 2020
])) -> datetime:
"""Parse a given text representing a partial date using a list of formats,
adjusting it to the last day of the month.
"""
date = parse_datetime(text, formats, to_utc=False)
_, last_day = calendar.monthrange(date.year, date.month)
return date.replace(day=last_day)
def parse_datetime(text, formats=frozenset([
"%Y-%m-%d %H:%M:%S", # 2023-05-01 08:32:34
"%Y-%m-%dT%H:%M:%S", # 2023-05-01T08:32:34
"%Y-%m-%d %H:%M:%S %z", # 2023-05-01 08:32:34 +0900
"%a, %d %b %Y %H:%M:%S %Z", # Wed, 01 Jan 2020 00:00:00 GMT
"%Y-%m-%dT%H:%M:%S%z", # 2023-05-01T08:32:34+0900
]), to_utc=True) -> datetime:
"""Parse a given text representing a datetime using a list of formats,
optionally converting it to UTC.
"""
text = text.strip()
for fmt in formats:
try:
date = datetime.strptime(text, fmt)
date = date.astimezone(timezone.utc) if to_utc else date
return date
except ValueError:
pass
raise ValueError(f"'{text}' could not be parsed as a date with any of the formats: {str(formats)}")