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.
return datetime_to_date_and_time(dt)[1]
-class TimeUnit(enum.Enum):
+class TimeUnit(enum.IntEnum):
"""An enum to represent units with which we can compute deltas."""
MONDAYS = 0
return False
-def n_timeunits_from_base(
- count: int, unit: TimeUnit, base: datetime.datetime
-) -> datetime.datetime:
+def n_timeunits_from_base(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
years before base datetime, 13 minutes after base datetime, etc...
>>> n_timeunits_from_base(50, TimeUnit.SECONDS, base)
datetime.datetime(2021, 9, 10, 11, 25, 41, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
+ Next month corner case -- it will try to make Feb 31, 2022 then count
+ backwards.
+ >>> base = string_to_datetime("2022/01/31 11:24:51AM-0700")[0]
+ >>> n_timeunits_from_base(1, TimeUnit.MONTHS, base)
+ datetime.datetime(2022, 2, 28, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
+
+ Last month with the same corner case
+ >>> base = string_to_datetime("2022/03/31 11:24:51AM-0700")[0]
+ >>> n_timeunits_from_base(-1, TimeUnit.MONTHS, base)
+ datetime.datetime(2022, 2, 28, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
+
"""
assert TimeUnit.is_valid(unit)
if count == 0:
base += timedelta
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
- ):
+ if base.weekday() < 5 and datetime.date(base.year, base.month, base.day) not in skips:
count -= 1
return base
new_month %= 12
year_term += 1
new_year = base.year + year_term
- return datetime.datetime(
- new_year,
- new_month,
- base.day,
- base.hour,
- base.minute,
- base.second,
- base.microsecond,
- base.tzinfo,
- )
+ day = base.day
+ while True:
+ try:
+ ret = datetime.datetime(
+ new_year,
+ new_month,
+ day,
+ base.hour,
+ base.minute,
+ base.second,
+ base.microsecond,
+ base.tzinfo,
+ )
+ break
+ except ValueError:
+ day -= 1
+ return ret
# N years from base
elif unit == TimeUnit.YEARS:
'1 day, and 10 minutes'
"""
- return describe_duration(delta.total_seconds())
+ return describe_duration(int(delta.total_seconds())) # Note: drops milliseconds
def describe_duration_briefly(seconds: int, *, include_seconds=False) -> str:
'1d 10m'
"""
- return describe_duration_briefly(delta.total_seconds())
+ return describe_duration_briefly(int(delta.total_seconds())) # Note: drops milliseconds
if __name__ == '__main__':