Недавно я сделал приложение для отслеживания дней рождения, которое в основном считывает информацию name
/birthdate
из файла CSV
, помещает все данные в объекты Person
и упорядочивает их по дате в списке, а затем переупорядочивает список, чтобы он начинался с текущей даты. .
Например, прямо сейчас первые несколько элементов в списке имеют даты рождения в конце November
и December
, а остальные следуют по порядку, начиная с January
и заканчивая November 23rd
.
Дело в том, что в какой-то момент в моей программе мне нужно отобразить текущие дни рождения (просто, просто вытащите первый элемент списка, если его дата рождения равна текущей дате), а также предстоящие дни рождения. Вот код для него:
today_plus_3weeks = today + d.timedelta(days=21)
# Take people who were born today and put them in a separate list
while people[0].birthdate.month == today.month and people[0].birthdate.day == today.day:
birthdays_today.append(people.pop(0))
# Take people who were born on dates between tomorrow and x later (default 3 weeks)
# and put them in a separate list
while initPeople.is_first_date_later(today_plus_3weeks, people[0].birthdate):
upcoming_birthdays.append(people.pop(0))
До недавнего времени предстоящие дни рождения работали нормально, но сегодня я столкнулся с проблемой. Моя программа проверяет первые несколько предстоящих дат, и все они в пределах трех недель. Однако следующая дата находится в January—
, поэтому теоретически она должна быть отклонена программой, и цикл должен завершиться... но этого не происходит.
Проблема очевидна, если посмотреть на код, который я использую для сравнения дат:
def is_first_date_later(date1, date2):
"""Returns True if the first date is later in the year than the second, False if not"""
return date1.month > date2.month or (date1.month == date2.month and date1.day > date2.day)
Условие всегда True
, потому что дата, используемая для сравнения, находится в mid-December
, поэтому month
всегда больше, или, когда оно равно, day
больше. Поэтому я очищаю весь свой список и заканчиваю IndexError: list index out of range
. Я не могу использовать годы для сравнения, потому что даты разнятся на несколько лет, а годы не имеют значения для использования в этом контексте. У меня есть к ним доступ, если они мне когда-нибудь понадобятся.
Я действительно не уверен, каким было бы лучшее решение без значительного усложнения кода.
Если нужно, полный код доступен здесь.
Я бы начал с написания функции для определения года и даты чьего-то следующего дня рождения. Есть два случая:
def next_birthday(birthday_month, birthday_dayofmonth):
today = datetime.date.today()
bday_this_year = datetime.date(year=today.year, month=birthday_month, day=birthday_dayofmonth)
bday_next_year = datetime.date(year=today.year + 1, month=birthday_month, day=birthday_dayofmonth)
if bday_this_year >= today:
return bday_this_year
elif bday_next_year >= today:
return bday_next_year
else:
raise Exception("This is impossible")
Затем вы можете использовать эту функцию, чтобы найти количество дней до следующего дня рождения. Библиотека datetime позволяет вычитать даты и находить количество дней между ними.
def days_until_next_birthday(birthday_month, birthday_dayofmonth):
"""Days until next birthday. If it is their birthday, return 0."""
today = datetime.date.today()
next_bday = next_birthday(birthday_month, birthday_dayofmonth)
return (next_bday - today).days
Я думаю, проблема в том, что дата более поздняя или более ранняя, чем другая, не может быть четко определена в отсутствие года. 6 января 2022 года раньше 6 июля 2022 года, но позже 6 июля 2021 года.