# bot/utils/date_utils.py from datetime import datetime, timedelta import pytz def ensure_datetime(value): """ Приводит значение к объекту datetime с учетом временной зоны. :param value: Значение даты (строка или datetime). :return: Объект datetime. :raises: TypeError, если передан некорректный тип. """ if isinstance(value, str): try: # Если строка соответствует формату ISO 8601 return datetime.fromisoformat(value) except ValueError: raise ValueError(f"Некорректный формат даты: {value}") elif isinstance(value, datetime): return value else: raise TypeError(f"Ожидался тип str или datetime, получено: {type(value)}") def get_period_dates(period, now=None): """ Возвращает диапазон дат (start_date, end_date) для заданного периода. :param period: Период (строка: 'today', 'yesterday', 'last_week', 'last_month'). :param now: Текущая дата/время (опционально). :return: Кортеж (start_date, end_date). :raises: ValueError, если период не поддерживается. """ if now is None: now = datetime.now(pytz.UTC) if period == "today": start_date = now.replace(hour=0, minute=0, second=0, microsecond=0) end_date = now.replace(hour=23, minute=59, second=59, microsecond=999999) elif period == "yesterday": start_date = (now - timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0) end_date = (now - timedelta(days=1)).replace(hour=23, minute=59, second=59, microsecond=999999) elif period == "last_week": start_date = (now - timedelta(days=now.weekday() + 7)).replace(hour=0, minute=0, second=0, microsecond=0) end_date = (start_date + timedelta(days=6)).replace(hour=23, minute=59, second=59, microsecond=999999) elif period == "last_month": first_day_of_current_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0) last_day_of_previous_month = first_day_of_current_month - timedelta(days=1) start_date = last_day_of_previous_month.replace(day=1) end_date = last_day_of_previous_month.replace(hour=23, minute=59, second=59, microsecond=999999) else: raise ValueError(f"Неподдерживаемый период: {period}") return start_date, end_date