Методы подсчёта дней в Python: от базовых до продвинутых
Подсчёт количества дней средствами Python
Наиболее эффективное решение для подсчёта разницы между двумя датами - использование модуля datetime и типа date (или datetime). Вычитание одной даты из другой возвращает объект timedelta, у которого атрибут days содержит искомое количество дней.
from datetime import date
d1 = date(2024, 1, 1)
d2 = date(2024, 12, 31)
delta = d2 - d1
print(delta.days) # 365количество дней python (подсчёт количества дней в python)
Подход прост, поддерживается встроенной библиотекой и работает без дополнительных зависимостей. Подходит для большинства задач, где не требуется учёт времени суток или часовых поясов.
Как определить количество дней между двумя датами с учётом времени?
from datetime import datetime, timedelta
dt1 = datetime(2024, 3, 1, 10, 30)
dt2 = datetime(2024, 3, 15, 14, 45)
delta = dt2 - dt1
print(delta.days) # 14 (целых дней)
print(delta.total_seconds() / 86400) # 14.177... (с дробной частью)
Разность объектов datetime даёт timedelta с учётом часов, минут и секунд. Если нужны только полные дни, используется атрибут days. Для учёта дробной части - деление на количество секунд в сутках.
pytz для корректного вычисления.Как получить количество дней в конкретном месяце (например, феврале 2024)?
import calendar
year = 2024
month = 2
days_in_month = calendar.monthrange(year, month)[1]
print(days_in_month) # 29
Функция monthrange возвращает кортеж из первого дня недели и количества дней. Индекс [1] даёт число дней. Метод работает для любого года, учитывая високосность.
Как узнать количество дней в году (365 или 366)?
import calendar
year = 2024
if calendar.isleap(year):
days = 366
else:
days = 365
print(days) # 366
Проверка на високосность с помощью calendar.isleap(). Альтернатива - взять разность между 1 января следующего года и 1 января текущего.
Как посчитать количество рабочих дней между датами (без учёта праздников)?
import numpy as np
start = np.datetime64('2024-01-01')
end = np.datetime64('2024-01-31')
workdays = np.busday_count(start, end)
print(workdays) # 23
Функция numpy.busday_count считает будние дни (пн-пт) между двумя датами, исключая выходные. Для учёта государственных праздников можно передать массив holidays.
numpy способ недоступен. Для альтернативы можно написать цикл по датам с проверкой weekday() < 5, что менее эффективно на больших диапазонах.Как определить количество дней от начала года до заданной даты (порядковый номер дня в году)?
from datetime import date
d = date(2024, 3, 15)
day_of_year = d.timetuple().tm_yday
print(day_of_year) # 75
Метод timetuple() возвращает struct_time, в котором поле tm_yday содержит день года (от 1 до 366). Это эквивалентно d.toordinal() - date(d.year, 1, 1).toordinal() + 1.
Как вычислить возраст в днях?
from datetime import date
birth = date(1990, 6, 15)
today = date(2024, 12, 1)
age_days = (today - birth).days
print(age_days) # 12583
Просто вычесть дату рождения из текущей даты. Результат в днях не учитывает високосные годы как отдельные сутки - timedelta делает это автоматически.
Как определить количество дней между датами в списке (например, для нескольких пар)?
from datetime import date
pairs = [(date(2024,1,1), date(2024,1,10)), (date(2024,2,1), date(2024,2,15))]
deltas = [(b - a).days for a, b in pairs]
print(deltas) # [9, 14]
Генератор списка применяет вычитание ко всем парам. Эффективно для небольших наборов данных.
Расширенные примеры подсчёта дней
# Пример 1: Количество дней между двумя моментами времени с учётом часовых поясов
from datetime import datetime
import pytz
moscow = pytz.timezone('Europe/Moscow')
ny = pytz.timezone('America/New_York')
dt1 = moscow.localize(datetime(2024, 3, 10, 12, 0))
dt2 = ny.localize(datetime(2024, 3, 10, 12, 0))
# Приводим обе к UTC
utc1 = dt1.astimezone(pytz.UTC)
utc2 = dt2.astimezone(pytz.UTC)
print((utc2 - utc1).days) # 0 (оба полдня, но в разных поясах; разница всего несколько часов)
0
Без приведения к UTC разница могла бы составить -8 или +3 дня, в зависимости от порядка вычитания. Всегда приводите aware-даты к единому времени.
# Пример 2: Количество дней между датами с точностью до месяца (relativedelta)
from dateutil.relativedelta import relativedelta
from datetime import date
d1 = date(2023, 1, 31)
d2 = date(2023, 3, 1)
rd = relativedelta(d2, d1)
print(rd.years, rd.months, rd.days) # 0 1 1
0 1 1
relativedelta разлагает разницу на годы, месяцы, дни. В отличие от timedelta, учитывает разное количество дней в месяцах. Для подсчёта полных месяцев между датами этот модуль незаменим.
# Пример 3: Количество рабочих дней с учётом праздников (numpy)
import numpy as np
holidays = ['2024-01-01', '2024-01-08'] # Новый год и Рождество
start = np.datetime64('2024-01-01')
end = np.datetime64('2024-01-15')
workdays = np.busday_count(start, end, holidays=holidays)
print(workdays) # 9 (с 01.01 по 15.01 вычитаем 2 выходных и 2 праздника = 11 - 2 праздника = 9)
9
Параметр holidays принимает список дат в формате 'YYYY-MM-DD'. Numpy автоматически исключает как выходные, так и переданные праздничные дни.
# Пример 4: Количество дней между датами в pandas Series
import pandas as pd
dates = pd.Series(pd.date_range('2024-01-01', periods=5, freq='D'))
print(dates.diff().dt.days)
0 NaN 1 1.0 2 1.0 3 1.0 4 1.0 dtype: float64
diff() вычисляет разницу между последовательными элементами. Атрибут .dt.days извлекает количество целых дней. Удобно для анализа временных рядов.
# Пример 5: Количество дней от даты до конца года (ordinal)
from datetime import date
d = date(2024, 6, 15)
end_of_year = date(d.year, 12, 31)
days_left = end_of_year.toordinal() - d.toordinal()
print(days_left) # 199
199
Метод toordinal() возвращает последовательный номер дня (1 = 01.01.0001). Разность даёт точное количество дней без создания промежуточного timedelta.
# Пример 6: Количество дней с использованием юлианского календаря (через jdcal)
import jdcal
# Преобразуем григорианскую дату в юлианскую
jd = jdcal.gcal2jd(2024, 3, 1)
print(jd) # (2460375.5, 0.5) -> сумма = 2460376.0 (юлианская дата)
# Для разницы между двумя датами
jd1 = sum(jdcal.gcal2jd(2024, 1, 1))
jd2 = sum(jdcal.gcal2jd(2024, 3, 1))
print(jd2 - jd1) # 60.0 (ровно 60 дней)
60.0
Библиотека jdcal (устанавливается отдельно) позволяет работать с юлианским календарём. Полезна для астрономических расчётов или исторических данных.
# Пример 7: Количество дней между двумя датами с помощью datetime.timestamp (опасность)
from datetime import datetime
dt1 = datetime(2024, 1, 1)
dt2 = datetime(2024, 12, 31)
delta_sec = dt2.timestamp() - dt1.timestamp()
print(delta_sec / 86400) # 365.0
365.0
Преобразование в timestamp (секунды с 1970-01-01) и деление на 86400 даёт количество дней. Однако этот способ чувствителен к високосным секундам и часовым поясам. Не рекомендуется для точных расчётов, лучше использовать timedelta.