Source code for lib.dates

"""Helper functions/classes related to dates/datetimes."""

import datetime as dt
import re
from typing import List

from dateutil.parser import parse as dateutil_parse

from .types import DateLike, assert_never


[docs]def parse_date(date: DateLike) -> dt.date: """Parses a date string. Args: date: The date string to parse. This function defaults to using dateutil.parser.parse(), but also accepts the following special formats for ``date``: @t | @today Today's date. Nd N days ago. Nw N weeks ago. """ if isinstance(date, str): date = date.lower() match = re.match("^(?P<num>[0-9]+)(?P<ch>d|w)$", date) if match: num = int(match.group("num")) ch = match.group("ch") if ch == "d": days = num else: assert ch == "w" days = 7 * num return dt.date.today() - dt.timedelta(days=days) if date in ["@today", "@t"]: return dt.date.today() elif isinstance(date, str): datetime = dateutil_parse(date) return datetime.date() elif isinstance(date, dt.datetime): return date.date() elif isinstance(date, dt.date): return date else: assert_never(date)
[docs]def parse_daterange(daterange: str) -> List[dt.date]: """Transforms a date range specifier into a list of sequential dates. Args: daterange: A string of the form START_DATE:END_DATE where both START_DATE and END_DATE are any value that the parse_date() function can parse. """ if ":" not in daterange: return [parse_date(daterange)] else: first_date, last_date = [parse_date(D) for D in daterange.split(":")] result = [] next_date = first_date while next_date <= last_date: result.append(next_date) next_date = next_date + dt.timedelta(days=1) return result