summaryrefslogtreecommitdiff
path: root/datetime_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'datetime_utils.py')
-rw-r--r--datetime_utils.py119
1 files changed, 61 insertions, 58 deletions
diff --git a/datetime_utils.py b/datetime_utils.py
index 7c5516b..9794720 100644
--- a/datetime_utils.py
+++ b/datetime_utils.py
@@ -27,18 +27,16 @@ 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 +55,20 @@ 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 +85,9 @@ 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 +131,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 +170,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 +195,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 +237,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 +268,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 +349,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 +395,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 +423,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 +505,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 +538,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 +707,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 +818,5 @@ def describe_timedelta_briefly(delta: datetime.timedelta) -> str:
if __name__ == '__main__':
import doctest
+
doctest.testmod()