Была у меня одна простенькая задачка - определять по дате рождения пенсионер человек или нет.
До недавнего времени отлично работало следующее решение: из текущей даты вычитаем 60 и 55 лет и получаем минимальную дату рождения мужчины и женщины, для которых наступил пенсионный возраст. После этого сравниваем эту дату с датой рождения конкретного человека и определяем пенсионер он или нет. Ниже приведён код данного решения (только обсуждаемая часть):
- import datetime
-
- now_date = datetime.date.today()
- cur_year = now_date.year
- men_retirement_date = now_date.replace(year = cur_year - 60)
- women_retirement_date = now_date.replace(year = cur_year - 55)
-
- ...
-
- for people in list:
- if isMale:
- isPensioner = brs_date < men_retirement_date
- else:
- isPensioner = brs_date < women_retirement_date
import datetime
now_date = datetime.date.today() # Текущая дата (без времени)
cur_year = now_date.year # Год текущий
men_retirement_date = now_date.replace(year = cur_year - 60)
women_retirement_date = now_date.replace(year = cur_year - 55)
...
for people in list:
if isMale:
isPensioner = brs_date < men_retirement_date
else:
isPensioner = brs_date < women_retirement_date
Решение было всем хорошее, кроме одного момента - при вычитании годов (для определения даты выхода на пенсию) не учитывалось, что в високосные годы в феврале на 1 день больше, поэтому при запуске 29 февраля программка вылетела с ошибкой преобразования даты.
Теперь же, после принятия новой пенсионной реформы, появился переходный период и пришлось писать отдельную функцию для того же функционала (посмотреть код).
- import datetime
-
- def isPensioner(isMale, dtBirth):
-
-
-
-
-
-
- is_pensioner = False
- retirement_age = 55
- addhalfyear = False
-
- retirement_date = dtBirth
- birth_year = dtBirth.year
- birth_month = dtBirth.month
- birth_day = dtBirth.day
-
- if isMale:
- if birth_year <= 1958:
- retirement_age = 60
- elif birth_year == 1959:
- retirement_age = 60
- addhalfyear = True
- elif birth_year == 1960:
- retirement_age = 61
- addhalfyear = True
- elif birth_year == 1961:
- retirement_age = 63
- elif birth_year == 1962:
- retirement_age = 64
- else:
- retirement_age = 65
- else:
- if birth_year <= 1963:
- retirement_age = 55
- elif birth_year == 1964:
- retirement_age = 55
- addhalfyear = True
- elif birth_year == 1965:
- retirement_age = 56
- addhalfyear = True
- elif birth_year == 1966:
- retirement_age = 58
- elif birth_year == 1967:
- retirement_age = 59
- else:
- retirement_age = 60
-
-
- if birth_day > 28:
- retirement_date = retirement_date.replace(day = 28)
- retirement_date = retirement_date.replace(year = birth_year + retirement_age)
- if addhalfyear:
- if birth_month > 6:
- retirement_date = retirement_date.replace(year = birth_year + retirement_age + 1)
- retirement_date = retirement_date.replace(month = birth_month + 6 - 12)
- else:
- retirement_date = retirement_date.replace(month = birth_month + 6)
- if birth_day > 28:
- nday = 28
- while nday < birth_day:
- nday += 1
- try:
- retirement_date = retirement_date.replace(day = nday)
- except ValueError:
- pass
-
- is_pensioner = now_date > retirement_date
- return is_pensioner
-
- for people in list:
- if isMale:
- isPensioner = isPensioner(True, brs_date)
- else:
- isPensioner = isPensioner(False, brs_date)
import datetime
def isPensioner(isMale, dtBirth):
"""Вычисляет является человек пенсионером или нет.
Параметры:
isMale - пол: для мужчин - True, для женщин - False
dtBirth - дата рождения"""
is_pensioner = False # пенсионер?
retirement_age = 55
addhalfyear = False
retirement_date = dtBirth
birth_year = dtBirth.year
birth_month = dtBirth.month
birth_day = dtBirth.day
if isMale:
if birth_year <= 1958:
retirement_age = 60
elif birth_year == 1959:
retirement_age = 60
addhalfyear = True
elif birth_year == 1960:
retirement_age = 61
addhalfyear = True
elif birth_year == 1961:
retirement_age = 63
elif birth_year == 1962:
retirement_age = 64
else:
retirement_age = 65
else: # Female
if birth_year <= 1963:
retirement_age = 55
elif birth_year == 1964:
retirement_age = 55
addhalfyear = True
elif birth_year == 1965:
retirement_age = 56
addhalfyear = True
elif birth_year == 1966:
retirement_age = 58
elif birth_year == 1967:
retirement_age = 59
else:
retirement_age = 60
# прибавим к дате рождения пенсионный возраст
if birth_day > 28:
retirement_date = retirement_date.replace(day = 28)
retirement_date = retirement_date.replace(year = birth_year + retirement_age)
if addhalfyear:
if birth_month > 6:
retirement_date = retirement_date.replace(year = birth_year + retirement_age + 1)
retirement_date = retirement_date.replace(month = birth_month + 6 - 12)
else:
retirement_date = retirement_date.replace(month = birth_month + 6)
if birth_day > 28:
nday = 28
while nday < birth_day:
nday += 1
try:
retirement_date = retirement_date.replace(day = nday)
except ValueError:
pass
is_pensioner = now_date > retirement_date
return is_pensioner
for people in list:
if isMale:
isPensioner = isPensioner(True, brs_date)
else:
isPensioner = isPensioner(False, brs_date)
Учитывая необходимость добавления полугодовых интервалов, в ней также была реализована проверка корректности вновь формируемых дат: перед сдвигом если день больше 28 принудительно устанавливаем 28 число (т.к. такой день есть в любом месяце), далее производим необходимые манипуляции с датой (добавляем года и, при необходимости, месяцы), а потом пробуем поднять дату до необходимой, перехватывая возможные исключения.
PS Для прибавления 6 месяцев к указанной дате на StackOverflow предложили использовать отдельную библиотеку dateutil, но мне показалось, что в данном случае это было бы избыточно, да и лишнюю зависимость "тащить" не хотелось. Ниже предложенное там решение:
- from datetime import date
- from dateutil.relativedelta import relativedelta
-
- six_months = date.today() + relativedelta(months=+6)
from datetime import date
from dateutil.relativedelta import relativedelta
six_months = date.today() + relativedelta(months=+6)
Напомню, что предварительно библиотеку надо установить: pip install python-dateutil