زمان، سختتر از آن است که به نظر میرسد
ماژول استاندارد datetime چند نوع اصلی دارد: date (فقط تاریخ)، datetime (تاریخ و ساعت)، timedelta (فاصلهی زمانی) و timezone. از Python 3.9 هم ماژول zoneinfo منطقههای زمانی واقعی مثل Asia/Tehran را میشناسد.
from datetime import date, datetime, timedelta, UTC
from zoneinfo import ZoneInfo
TEHRAN = ZoneInfo("Asia/Tehran")
now = datetime.now(TEHRAN) # زمان «آگاه» (aware) با منطقهی زمانی
print(now.isoformat()) # مثلاً 2026-09-28T14:05:12+03:30
print(now.astimezone(UTC)) # همان لحظه به وقت جهانی
due = date.today() + timedelta(days=45) # تحویل ۴۵ روز بعد
days_left = (due - date.today()).days
stamp = datetime.strptime("2025-03-20 14:30", "%Y-%m-%d %H:%M") # رشته به تاریخ
print(stamp.strftime("%d/%m/%Y")) # تاریخ به رشته
naive در برابر aware
datetime.now() بدون آرگومان یک زمان naive میدهد: عدد ساعت دارد ولی نمیداند مال کدام منطقه است. روی لپتاپ شما وقت تهران است و روی سرور خارجی وقت UTC؛ و اختلاف سهونیم ساعتهای که گزارشها را به روز اشتباه میبرد. قاعده: در ذخیرهسازی UTC، در نمایش تهران. مقایسهی یک زمان naive با aware هم TypeError میدهد.
تاریخ شمسی با jdatetime
کتابخانهی استاندارد تقویم شمسی ندارد. کتابخانهی jdatetime رابطی تقریباً یکسان با datetime برای تقویم جلالی فراهم میکند:
python -m pip install jdatetime tzdata
import jdatetime
from datetime import date, datetime
today = jdatetime.date.today()
print(today.strftime("%Y/%m/%d")) # مثلاً 1405/07/06
j = jdatetime.date.fromgregorian(date=date(2025, 3, 21))
print(j) # 1404-01-01
print(jdatetime.date(1404, 1, 1).togregorian()) # 2025-03-21
jnow = jdatetime.datetime.fromgregorian(datetime=datetime.now(TEHRAN))
print(jnow.strftime("%Y/%m/%d %H:%M"))
parsed = jdatetime.datetime.strptime("1403/05/20", "%Y/%m/%d")
print(parsed.togregorian().date()) # 2024-08-10
jdatetime.set_locale(jdatetime.FA_LOCALE) # نام روز و ماه فارسی
print(jdatetime.date(1404, 1, 1).strftime("%A %d %B %Y"))
راهبرد درست در یک برنامهی واقعی: همهجا با datetime میلادی (ترجیحاً UTC) کار و ذخیره کنید و فقط در لحظهی نمایش یا دریافت از کاربر، به شمسی تبدیل کنید. ذخیرهی رشتهی «۱۴۰۳/۰۵/۲۰» در دیتابیس، مرتبسازی، فیلتر بازه و محاسبهی فاصله را سخت و پرخطا میکند.
| کد قالب | معنی |
|---|---|
%Y / %m / %d | سال چهاررقمی / ماه / روز |
%H:%M:%S | ساعت ۲۴ ساعته |
%A / %B | نام روز هفته / نام ماه |
%j | شمارهی روز در سال |
نکتههایی که کمتر کسی میداند
- ویندوز پایگاه دادهی منطقههای زمانی IANA را ندارد؛ بدون نصب بستهی
tzdata، دستورZoneInfo("Asia/Tehran")در ویندوز خطای ZoneInfoNotFoundError میدهد. - ایران از سال ۱۴۰۲ دیگر ساعت تابستانی ندارد؛ tzdata بهروز این را میداند. اگر اختلاف تهران در سرور شما در تابستان +04:30 است، tzdata سیستم قدیمی است.
datetime.utcnow()در Python 3.12 منسوخ (deprecated) شده، چون زمان naive برمیگرداند؛ بهجایشdatetime.now(UTC)بنویسید.jdatetime.date(1403, 12, 30)معتبر است (۱۴۰۳ کبیسه بود) ولیjdatetime.date(1404, 12, 30)ValueError میدهد؛ اعتبارسنجی ورودی تاریخ شمسی را به خود کتابخانه بسپارید وisleap()را برای بررسی سال به کار ببرید.datetime.fromisoformatاز 3.11 تقریباً هر رشتهی ISO 8601 (از جمله+03:30وZ) را میخواند و برای دادهی API ها بهترین انتخاب است.