Source code for businessdate.daycount

# -*- coding: utf-8 -*-

# businessdate
# ------------
# Python library for generating business dates for fast date operations
# and rich functionality.
#
# Author:   sonntagsgesicht, based on a fork of Deutsche Postbank [pbrisk]
# Version:  0.5, copyright Wednesday, 18 September 2019
# Website:  https://github.com/sonntagsgesicht/businessdate
# License:  Apache License 2.0 (see LICENSE file)


from datetime import date
from .ymd import is_leap_year


[docs]def diff_in_days(start, end): """ calculates days between start and end date """ if hasattr(start, 'to_date'): start = start.to_date() if hasattr(end, 'to_date'): end = end.to_date() return float((end-start).days)
[docs]def get_30_360(start, end): """ implements 30/360 Day Count Convention. """ start_day = min(start.day, 30) end_day = 30 if (start_day == 30 and end.day == 31) else end.day return (360 * (end.year - start.year) + 30 * (end.month - start.month) + (end_day - start_day)) / 360.0
[docs]def get_30e_360(start, end): """ implements the 30E/360 Day Count Convention. """ y1, m1, d1 = start.timetuple()[:3] # adjust to date immediately following the the last day y2, m2, d2 = end.timetuple()[:3] d1 = min(d1, 30) d2 = min(d2, 30) return (360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1)) / 360.0
[docs]def get_30e_360i(start, end): """ implements the 30E/360 I. Day Count Convention. """ y1, m1, d1 = start.timetuple()[:3] # adjust to date immediately following the last day y2, m2, d2 = end.timetuple()[:3] if (m1 == 2 and d1 >= 28) or d1 == 31: d1 = 30 if (m2 == 2 and d2 >= 28) or d2 == 31: d2 = 30 return (360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1)) / 360.0
[docs]def get_act_360(start, end): """ implements Act/360 day count convention. """ return diff_in_days(start, end) / 360.0
[docs]def get_act_365(start, end): """ implements Act/365 day count convention. """ return diff_in_days(start, end) / 365.0
[docs]def get_act_36525(start, end): """ implements Act/365.25 Day Count Convention """ return diff_in_days(start, end) / 365.25
[docs]def get_act_act(start, end): """ implements Act/Act day count convention. """ # if the period does not lie within a year split the days in the period as following: # remaining days of start year / years in between / days in the end year # REMARK: following the before mentioned Definition the first day of the period is included whereas the # last day will be excluded # What remains to check now is only whether the start and end year are leap or non-leap years. The quotients # can be easily calculated and for the years in between they are always one (365/365 = 1; 366/366 = 1) if end.year - start.year == 0: if is_leap_year(start.year): return diff_in_days(start, end) / 366.0 # leap year: 366 days return diff_in_days(start, end) / 365.0 # non-leap year: 365 days rest_year1 = diff_in_days(start, date(start.year, 12, 31)) + 1 # since the first day counts rest_year2 = abs(diff_in_days(end, date(end.year, 1, 1))) # here the last day is automatically not counted years_in_between = end.year - start.year - 1 return years_in_between + rest_year1 / (366.0 if is_leap_year(start.year) else 365.0) + rest_year2 / ( 366.0 if is_leap_year(end.year) else 365.0)