اول معنای شمارش روز را تعیین کنید

پرسش «بین دو تاریخ چند روز است؟» می‌تواند چند جواب قراردادی داشته باشد. اختلاف تقویمی، شمارش شامل هر دو سر و شمارش روزهای کاری یکسان نیستند. این آموزش اختلاف end منهای start را می‌گیرد؛ روز آغاز جداگانه به نتیجه اضافه نمی‌شود. اگر دو تاریخ برابر باشند، جواب صفر است. همین تعریف کوتاه جلوی خطای رایج یک روز اضافه یا کم را می‌گیرد.

تاریخ بدون ساعت را ساده نگه دارید

ورودی پروژه تاریخ میلادی بدون ساعت و منطقهٔ زمانی است. بنابراین موضوع ساعت تابستانی یا تبدیل UTC وارد محاسبه نمی‌شود. برای زمان دقیق رخدادها باید datetime آگاه از منطقهٔ زمانی و سیاست تبدیل داشته باشید. تبدیل تاریخ شمسی نیز با عوض‌کردن قالب نمایش انجام نمی‌شود و کتابخانه و قرارداد جدا می‌خواهد. در این تمرین از دادهٔ YYYY-MM-DD استفاده می‌کنیم تا مسئله محدود و بازتولیدپذیر بماند.

چرا قالب دقیق را دوباره بررسی می‌کنیم؟

برخی ابزارهای تجزیه ممکن است شکل‌هایی انعطاف‌پذیرتر از قرارداد بپذیرند. پس بعد از تجزیه، خروجی isoformat را با متن ورودی مقایسه می‌کنیم تا صفرهای ماه و روز نیز الزامی باشند. این بررسی با معتبر بودن خود تاریخ متفاوت است: ۲۰۲۵-۰۲-۲۹ از نظر تقویم نامعتبر است، اما ۲۰۲۶-۱-۰۱ از نظر قالب پروژه رد می‌شود. خطای قابل‌پیش‌بینی برای هر دو حالت به خروجی قراردادی تبدیل می‌شود.

محاسبه را به تقویم استاندارد بسپارید

تفاضل دو شیء date یک timedelta تولید می‌کند و ویژگی days تعداد روزهای کامل اختلاف را می‌دهد. تلاش برای ضرب ماه در سی یا سال در سیصدوشصت‌وپنج به مرز ماه‌ها و سال کبیسه آسیب می‌زند. مثال عبور از فوریهٔ سال کبیسه دقیقاً برای آشکارکردن این خطا مفید است. کتابخانهٔ استاندارد قواعد تقویم را اعمال می‌کند؛ شما باید معنای ورودی و خروجی را مشخص کنید.

بازهٔ معکوس را پنهان نکنید

در این قرارداد اگر پایان قبل از آغاز باشد، اختلاف منفی برمی‌گردد. استفادهٔ خودکار از abs این اطلاعات را از بین می‌برد و ممکن است دادهٔ وارونه را ظاهراً درست نشان دهد. در محصولی مثل رزرو، شاید بازهٔ معکوس باید خطا باشد؛ آن رفتار مشروع است اما قرارداد دیگری محسوب می‌شود. انتخاب بین عدد منفی و خطا باید در نیازمندی و تست یکسان نوشته شود.

خطا را محدود و قابل‌استفاده برگردانید

ورودی نامعتبر با error برابر invalid_date گزارش می‌شود و در آن حالت کلید days وجود ندارد. نباید همهٔ استثناها را بدون تمایز ببلعید؛ اشکال برنامه‌نویسی با خطای کاربر یکی نیست. در این تمرین نوع فیلدها رشته فرض شده و خطای قالب یا مقدار تاریخ مدیریت می‌شود. برای API واقعی، نبودن فیلد و نوع نامناسب نیز در مرز ورودی باید قرارداد جدا و پاسخ روشن داشته باشد.

فهرست آزمون و تمرین بعدی

تاریخ برابر، بازهٔ معکوس، عبور از پایان سال، فوریهٔ کبیسه، روز نامعتبر و ماه بدون صفر ابتدایی را آزمایش کنید. نتیجهٔ موردانتظار را قبل از اجرا بنویسید تا کد معیار خودش نشود. برای توسعه، شمارش روز کاری بسازید و تعطیلات را ورودی صریح قرار دهید. فرض‌کردن اینکه همهٔ کشورها آخرهفتهٔ یکسان دارند یا تعطیلات همیشه ثابت‌اند، گزارش را غیرقابل‌اعتماد می‌کند.

نمونه‌کد و قرارداد پروژه

start و end رشتهٔ تاریخ میلادی با قالب دقیق YYYY-MM-DD؛ بدون ساعت و منطقهٔ زمانی. تاریخ نامعتبر باید خطا بدهد.

days: اختلاف علامت‌دار end-start بر حسب روز؛ روز آغاز شمرده نمی‌شود. تاریخ نامعتبر: فقط error=invalid_date.

from datetime import datetime


def solve(data):
    try:
        dates = []
        for name in ('start', 'end'):
            text = data[name]
            value = datetime.strptime(text, '%Y-%m-%d').date()
            if value.isoformat() != text:
                raise ValueError('Invalid format')
            dates.append(value)
        return {'days': (dates[1] - dates[0]).days}
    except ValueError:
        return {'error': 'invalid_date'}

print(solve({'start': '2026-01-01', 'end': '2026-01-10'}))

خروجی مورد انتظار

{
  "days": 9
}

پرسش‌های متداول

آیا روز آغاز هم شمرده می‌شود؟

در اختلاف end-start خیر. برای شمارش شامل دو سر باید قرارداد دیگری تعریف کنید و در بازهٔ معتبر یک واحد اضافه کنید.

آیا این کد تاریخ شمسی می‌گیرد؟

خیر. ورودی این تمرین میلادی است؛ تبدیل تقویم، اعتبارسنجی و نمایش شمسی به ابزار و آزمون جدا نیاز دارد.

تمرین عملی و قدم بعدی

پروژهٔ «شمارش روزهای یک بازه» همین قرارداد را در میزکار ارزیابی می‌کند. ابتدا خروجی نمونه را دستی محاسبه کنید، سپس تابع را اجرا کنید و یک ورودی مرزی متفاوت بسازید. نمونه‌کد راهی برای توضیح منطق است؛ برای یادگیری، علت هر شرط و انتخاب ساختار داده را بدون نگاه‌کردن به کد توضیح دهید. اجرای موفق با قبولی ارزیابی متفاوت است؛ نتیجه باید برای تمام حالت‌های تعریف‌شده درست بماند.

منابع و مطالعهٔ بیشتر

برای بررسی جزئیات و ادامهٔ مطالعه؛ متن این راهنما مستقلاً برای نوونتیکس نوشته شده است.