Запах кода 307 - предположения наивного времени и как его исправить

Запах кода 307 - предположения наивного времени и как его исправить

17 июля 2025 г.

Не изобретайте время. Вы, вероятно, делаете это неправильно

TL; DR: время не является абсолютным. Ваш код ломается, когда вы относитесь к нему таким образом.

Проблемы 😔

  • Неправильные продолжительности
  • Часовой поясхаос
  • Сломанное планирование
  • Дата диапазонадефекты
  • Неверныйвременные метки
  • ГлобальныйДаты
  • ТестыВ зависимости от дат

Решения 😃

  1. Используйте твердые библиотеки
  2. Избегатьсистемное доверие
  3. Нормализовать все временные метки
  4. Проверка с краевыми случаями
  5. Принимайте время странно
  6. Всегда включайте часовые пояса
  7. ПроверятьВсеЧасовые пояса
  8. Неудача
  9. Лечить временные метки какВременные метки

Контекст 💬

Вы думаете, что день состоит в 24 часах, недели начинаются в понедельник, или в феврале всегда 28 дней.

Ваши пользователи в Уагадугу получают двойную полуночи, и ваши резервные копии пропускают день в Сиднее.

Иллюзии времени проникают в ваш код, когда вы предполагаете, что это просто.

Вы строите логику, которая терпит неудачу во время дневного подсветка, изменений, прыжковых секунд или даже когда часы дрейфуют.

Программисты часто борются с управлением временем.

Когда вы работаете со временем в своих приложениях, вы сталкиваетесь с одной из самых обманных задач программирования.

Большинство разработчиков начинают с написания простых расчетов времени, предполагая, что дни всегда имеют 24 часа, месяцы имеют постоянную длину, а часовые пояса остаются статичными.

Эти предположения создаютдефектыЭта поверхность месяцев или годы спустя, когда ваше приложение сталкивается с реальными сценариями времени.

Работа с временем представляет собой прекрасный примерЭффект Даннинг-Кругерав программировании. Чем больше вы узнаете о времени, тем больше вы понимаете, насколько мало вы знаете.

Политические решения изменяют часовые пояса, прыжковые секунды корректируют атомное время, а культурные различия влияют на календарные системы по всему миру.

Пример кода 📖

Неправильно ❌

from datetime import datetime, timedelta

class TimeCalculator:
    def add_business_days(self, start_date, days):
        # Assumes every day has 24 hours
        result = start_date
        for _ in range(days):
            result += timedelta(days=1)
            # Skip weekends
            while result.weekday() >= 5:
                result += timedelta(days=1)
        return result
    
    def get_monthly_report_date(self, year, month):
        # Assumes all months have 31 days
        return datetime(year, month, 31)
    
    def calculate_age(self, birth_date):
        # Ignores leap years and timezone changes
        today = datetime.now()
        return (today - birth_date).days // 365
    
    def schedule_meeting(self, base_time, timezone_offset):
        # Assumes timezone offset never changes
        return base_time + timedelta(hours=timezone_offset)
    
    def is_same_day(self, time1, time2):
        # Compares without considering timezone
        return time1.date() == time2.date()

Справа 👉

import pytz
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from zoneinfo import ZoneInfo

class TimeHandler:
    def __init__(self, timezone='UTC'):
        self.timezone = ZoneInfo(timezone)
    
    def add_business_days(self, start_date, days):
        """Add business days accounting for timezone and DST"""
        if not start_date.tzinfo:
            start_date = start_date.replace(tzinfo=self.timezone)
        
        result = start_date
        days_added = 0
        
        while days_added < days:
            result += timedelta(days=1)
            # Skip weekends
            if result.weekday() < 5:
                days_added += 1
        
        return result
    
    def get_monthly_report_date(self, year, month):
        """Get last day of month safely"""
        next_month = datetime(year, month, 1, 
             tzinfo=self.timezone) + relativedelta(months=1)
        return next_month - timedelta(days=1)
    
    def calculate_age(self, birth_date):
        """Calculate age accounting for leap years"""
        if not birth_date.tzinfo:
            birth_date = birth_date.replace(tzinfo=self.timezone)
        
        today = datetime.now(self.timezone)
        return relativedelta(today, birth_date).years
    
    def schedule_meeting(self, base_time, target_timezone):
        """Schedule meeting with proper timezone handling"""
        if not base_time.tzinfo:
            base_time = base_time.replace(tzinfo=self.timezone)
        
        target_tz = ZoneInfo(target_timezone)
        return base_time.astimezone(target_tz)
    
    def is_same_day(self, time1, time2, timezone):
        """Compare dates in specific timezone"""
        tz = ZoneInfo(timezone)
        local_time1 = time1.astimezone(tz)
        local_time2 = time2.astimezone(tz)
        return local_time1.date() == local_time2.date()

Обнаружение 🔍

  • [x]Полуавтоматический

Вы можете обнаружить этот запах, когда вы видите расчеты в жестком кодировании, предположения о длине дня, часовых операциях DateTime или арифметике даты.

Искатьмагические числаКак 86400 (секунды в день), 365 (дни в году) или хардкодированные смеси часового пояса.

Следите за операциями DateTime, которые не указывают часовые пояса, расчеты перейного года с использованием простого разделения или любого кода, который рассматривает время как чисто математическое, не рассматривая политические и физические реалии.

Теги 🏷

  • Время

Уровень 🔋

  • [x]Средний

Почему биение важна 🗺

Время в реальном мире нечеткое, политическое и полное исключений.

Если ваша программа моделирует это как линейное и идеальное, вы введете несоответствиеКартПолем

Это несоответствие приводит кдефектыкоторые невозможно воспроизвести и трудно объяснить.

Вы должны представлять время таким образом, чтобы отражать его поведение: с контекстом, правилами и изменчивостью.

Когда ваш код предполагает упрощенное поведение времени, вы нарушаете переписку между моделью времени и реальностью вашей программы.

Это создаетдефектыкоторые появляются случайным образом, когда ваше приложение сталкивается с реальными сценариями времени, такими какДневное время сэкономитьПереходы, прыжок или изменения часового пояса.

Поддержание биографии означает уважение к истинной сложности времени и использование установленных библиотек, которые правильно обрабатывают эти края.

Сломать этоперепискаПриводит к ошибкам планирования, неправильным возрастным расчетам и повреждению данных в приложениях, чувствительных во времени.

Вы не можете создать дату с днем 30 февраля.

Вам нужно следоватьнеудачапринцип.

Поколение AI 🤖

ИИ часто предполагаетНовая дата ()работает нормально. Многие сгенерированные примеры игнорируют часовые пояса, изменения DST и даже правильный анализ. ИИ помогает вам быстрее повторять иллюзии.

Генераторы кодов ИИ иногда создают код обработки времени с общей ложью.

Они часто генерируют простую дату арифметической, твердых кодированных допущений часового пояса и наивных операций DateTime, потому что эти модели иногда случаются в учебных данных.

Обнаружение ИИ 🧲

Если вы попросите ИИ «правильно справитьсядефекты, «Это может генерировать лучший код. Но ему нужны четкие инструкции. Вывод по умолчанию обычно неправильный.

Инструменты искусственного интеллекта могут обнаружить неверную обработку времени, когда вы предоставляете конкретные инструкции о осознании часового пояса, обработке лечебного года и соображениях DST.

Вы должны явно запросить эти проверки, так как ИИ не будет автоматически идентифицировать связанные с временем предположения.

Попробуйте их! 🛠

Помните: помощники ИИ делают много ошибок

Предлагаемое подсказка: «Просмотрите этот код обработки времени на предмет общей ложь о времени. Проверьте на наличие операций с часовым поясом, жесткой длины дня/месяц, допущений на лечебное год и обработки DST. Предложите улучшения с использованием установленных библиотек времени и надлежащей обработки часового пояса».

Без надлежащих инструкций

С конкретными инструкциями

Чатгпт

Чатгпт

Клод

Клод

Недоумение

Недоумение

Второй пилот

Второй пилот

Ты

Ты

Близнецы

Близнецы

DeepSeek

DeepSeek

Meta ai

Meta ai

Грок

Грок

Qwen

Qwen

Заключение 🏁

Когда вы рассматриваете время как простое, ваш код лежит. Время - это глубоко разбитая концепция, пронизанная политикой, исключениями и дрейфом.

Уважайте это и никогда не пишите свою собственную логику даты.

Используйте библиотеки, которые потратили десятилетия, исправляя то, что вы даже не можете увидеть.

Ваши приложения станут более надежными, когда вы уважаете истинную природу времени и используете правильные методы обработки времени с начала процесса разработки.

Отношения 👩‍❤

https://hackernoon.com/how-to-find-the-shooky-parts-of-your-code-part-viii-8mn3352

https://hackernoon.com/code-smell-246-modeling-expiration-dates

https://hackernoon.com/how-to-find-the-shooky-parts-of-your-code-part-xxxix

https://hackernoon.com/how-to-find-the-shooky-parts-of-your-code-part-xli

https://hackernoon.com/how-to-find-the-shooky-parts-of-your-code-part-xvi

Больше информации 📕

https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca?embedable=true

https://www.nasa.gov/solar-system/moon/nasa-to-develop-lunar-time-standard-for-exploration-initiatives/?embedable=true

https://hackernoon.com/fail-fast-philosophy-explained-si963vk9?embedable=true

https://en.wikipedia.org/wiki/dunning-kruger_effect

Отказ от ответственности 📘

Кодовые запахи - моимнениеПолем

Кредиты 🙏

ФотоЛуис КортеснаНеспособный


День может быть 23 часа. Или 25. Вы просто забыли.

Пол Форд

https://hackernoon.com/400-thought-предвидение-software-engineering-quotes?embedable=true


Эта статья является частью серии Codesmell.

https://hackernoon.com/how-to-find-the-shooky-parts-of-your-code-part-i-xqz3evd?embedable=true


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE