X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=datetime_utils.py;h=3565936fce66c1197a04a8926f902452e6350ac4;hb=f77068f0dc494d9394cdacafc6f719730926839f;hp=7c5516b594b314aed141b4494e7eed5b820770f3;hpb=7e6972bc7c8e891dc669645fa5969ed76fe38314;p=python_utils.git diff --git a/datetime_utils.py b/datetime_utils.py index 7c5516b..3565936 100644 --- a/datetime_utils.py +++ b/datetime_utils.py @@ -27,18 +27,14 @@ def is_timezone_aware(dt: datetime.datetime) -> bool: True """ - return ( - dt.tzinfo is not None and - dt.tzinfo.utcoffset(dt) is not None - ) + return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None def is_timezone_naive(dt: datetime.datetime) -> bool: return not is_timezone_aware(dt) -def replace_timezone(dt: datetime.datetime, - tz: datetime.tzinfo) -> datetime.datetime: +def replace_timezone(dt: datetime.datetime, tz: datetime.tzinfo) -> datetime.datetime: """ Replaces the timezone on a datetime object directly (leaving the year, month, day, hour, minute, second, micro, etc... alone). @@ -57,13 +53,18 @@ def replace_timezone(dt: datetime.datetime, """ return datetime.datetime( - dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, - tzinfo=tz + dt.year, + dt.month, + dt.day, + dt.hour, + dt.minute, + dt.second, + dt.microsecond, + tzinfo=tz, ) -def replace_time_timezone(t: datetime.time, - tz: datetime.tzinfo) -> datetime.time: +def replace_time_timezone(t: datetime.time, tz: datetime.tzinfo) -> datetime.time: """ Replaces the timezone on a datetime.time directly without performing any translation. @@ -80,8 +81,7 @@ def replace_time_timezone(t: datetime.time, return t.replace(tzinfo=tz) -def translate_timezone(dt: datetime.datetime, - tz: datetime.tzinfo) -> datetime.datetime: +def translate_timezone(dt: datetime.datetime, tz: datetime.tzinfo) -> datetime.datetime: """ Translates dt into a different timezone by adjusting the year, month, day, hour, minute, second, micro, etc... appropriately. The returned @@ -125,12 +125,7 @@ def date_to_datetime(date: datetime.date) -> datetime.datetime: datetime.datetime(2021, 12, 25, 0, 0) """ - return datetime.datetime( - date.year, - date.month, - date.day, - 0, 0, 0, 0 - ) + return datetime.datetime(date.year, date.month, date.day, 0, 0, 0, 0) def time_to_datetime_today(time: datetime.time) -> datetime.datetime: @@ -169,8 +164,9 @@ def time_to_datetime_today(time: datetime.time) -> datetime.datetime: return datetime.datetime.combine(now, time, tz) -def date_and_time_to_datetime(date: datetime.date, - time: datetime.time) -> datetime.datetime: +def date_and_time_to_datetime( + date: datetime.date, time: datetime.time +) -> datetime.datetime: """ Given a date and time, merge them and return a datetime. @@ -193,7 +189,7 @@ def date_and_time_to_datetime(date: datetime.date, def datetime_to_date_and_time( - dt: datetime.datetime + dt: datetime.datetime, ) -> Tuple[datetime.date, datetime.time]: """Return the component date and time objects of a datetime. @@ -235,6 +231,7 @@ def datetime_to_time(dt: datetime.datetime) -> datetime.time: class TimeUnit(enum.Enum): """An enum to represent units with which we can compute deltas.""" + MONDAYS = 0 TUESDAYS = 1 WEDNESDAYS = 2 @@ -265,9 +262,7 @@ class TimeUnit(enum.Enum): def n_timeunits_from_base( - count: int, - unit: TimeUnit, - base: datetime.datetime + count: int, unit: TimeUnit, base: datetime.datetime ) -> datetime.datetime: """Return a datetime that is N units before/after a base datetime. e.g. 3 Wednesdays from base datetime, 2 weeks from base date, 10 @@ -348,10 +343,8 @@ def n_timeunits_from_base( if base.year != old_year: skips = holidays.US(years=base.year).keys() if ( - base.weekday() < 5 and - datetime.date(base.year, - base.month, - base.day) not in skips + base.weekday() < 5 + and datetime.date(base.year, base.month, base.day) not in skips ): count -= 1 return base @@ -396,13 +389,17 @@ def n_timeunits_from_base( base.tzinfo, ) - if unit not in set([TimeUnit.MONDAYS, - TimeUnit.TUESDAYS, - TimeUnit.WEDNESDAYS, - TimeUnit.THURSDAYS, - TimeUnit.FRIDAYS, - TimeUnit.SATURDAYS, - TimeUnit.SUNDAYS]): + if unit not in set( + [ + TimeUnit.MONDAYS, + TimeUnit.TUESDAYS, + TimeUnit.WEDNESDAYS, + TimeUnit.THURSDAYS, + TimeUnit.FRIDAYS, + TimeUnit.SATURDAYS, + TimeUnit.SUNDAYS, + ] + ): raise ValueError(unit) # N weekdays from base (e.g. 4 wednesdays from today) @@ -420,14 +417,14 @@ def n_timeunits_from_base( def get_format_string( - *, - date_time_separator=" ", - include_timezone=True, - include_dayname=False, - use_month_abbrevs=False, - include_seconds=True, - include_fractional=False, - twelve_hour=True, + *, + date_time_separator=" ", + include_timezone=True, + include_dayname=False, + use_month_abbrevs=False, + include_seconds=True, + include_fractional=False, + twelve_hour=True, ) -> str: """ Helper to return a format string without looking up the documentation @@ -502,20 +499,21 @@ def datetime_to_string( include_dayname=include_dayname, include_seconds=include_seconds, include_fractional=include_fractional, - twelve_hour=twelve_hour) + twelve_hour=twelve_hour, + ) return dt.strftime(fstring).strip() def string_to_datetime( - txt: str, - *, - date_time_separator=" ", - include_timezone=True, - include_dayname=False, - use_month_abbrevs=False, - include_seconds=True, - include_fractional=False, - twelve_hour=True, + txt: str, + *, + date_time_separator=" ", + include_timezone=True, + include_dayname=False, + use_month_abbrevs=False, + include_seconds=True, + include_fractional=False, + twelve_hour=True, ) -> Tuple[datetime.datetime, str]: """A nice way to convert a string into a datetime. Returns both the datetime and the format string used to parse it. Also consider @@ -534,11 +532,9 @@ def string_to_datetime( include_dayname=include_dayname, include_seconds=include_seconds, include_fractional=include_fractional, - twelve_hour=twelve_hour) - return ( - datetime.datetime.strptime(txt, fstring), - fstring + twelve_hour=twelve_hour, ) + return (datetime.datetime.strptime(txt, fstring), fstring) def timestamp() -> str: @@ -705,7 +701,7 @@ def parse_duration(duration: str) -> int: return seconds -def describe_duration(seconds: int, *, include_seconds = False) -> str: +def describe_duration(seconds: int, *, include_seconds=False) -> str: """ Describe a duration represented as a count of seconds nicely. @@ -816,4 +812,5 @@ def describe_timedelta_briefly(delta: datetime.timedelta) -> str: if __name__ == '__main__': import doctest + doctest.testmod()