Source code for beansoup.utils.dates
"""Utilities for working with dates.
Attributes:
MONTHS (Dict[str, int]): a map from month names to
their ordinal values, starting at 1. The names are lowercase and
can be full names, three-letter abbreviations, or one- or two-digit
representations.
"""
import calendar
import datetime
import itertools
MONTHS = dict((name.lower(), i) for i, name in itertools.chain(
enumerate(calendar.month_abbr[1:], start=1),
enumerate(calendar.month_name[1:], start=1),
enumerate(['{0:1d}'.format(i) for i in range(1, 13)], start=1),
enumerate(['{0:02d}'.format(i) for i in range(1, 13)], start=1)))
[docs]def month_number(month):
"""Turns a month name into its corresponding month number.
It recognizes full and abbreviated (three letters) English month names
(case insensitive) as well as month number with or without a leading 0.
Args:
month (str): The name of a month or its three-letter abbreviation or
its numerical equivalent.
Returns:
Optional[int]: The number in [1,12] corresponding to the given month name,
or None if it does not recognize the given name.
"""
return MONTHS.get(month.lower()) if isinstance(month, str) else None
[docs]def add_biz_days(date, num_biz_days):
"""Add a number of business days to a date.
If the starting date falls on a weekend, it is moved to the next business
day before adding the delta.
Args:
date (datetime.date): The starting date.
num_biz_days (int): The number of business days to add to the starting date;
it must be non-negative.
Returns:
datetime.date: the offset date.
"""
assert num_biz_days >= 0, 'Invalid num_biz_days value ({}): must be non-negative'.format(num_biz_days)
# Break the delta into a number of full weeks and a remainder
num_weeks, num_biz_days_left = divmod(num_biz_days, 5)
num_days = num_weeks * 7 + num_biz_days_left
weekday = date.weekday() # Monday is weekday 0
# If the starting date falls on a weekend, move it to the next business day
if weekday >= 5:
num_days += 7 - weekday
weekday = 0
# If the number of business days left in the delta spans a weekend, add
# that in a well
if weekday + num_biz_days_left >= 5:
num_days += 2
return date + datetime.timedelta(days=num_days)