Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Asosiy turlar
- 2.2. Naive va aware
- 2.3. timedelta va arifmetika
- 2.4. Oy va yil qo'shish
- 2.5. Formatlash
- 2.6. Tahlil qilish
- 2.7. Nozik joylar
- 2.8. time moduli soatlari
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Turlar va arifmetika
- Misol 2 — Formatlash va tahlil
- Misol 3 — Tuzoqlar
- Misol 4 — Amaliy: obuna to'lovlari va ish kunlari
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
15.4-dars: datetime
15-QISM — STANDART KUTUBXONA · 4-dars
1. Kirish va motivatsiya
Sana va vaqt — dasturlashdagi eng "oddiy ko'rinadigan", lekin eng ko'p xato beradigan mavzulardan biri. Sabab: kalendar muntazam emas. Oylar 28, 29, 30 yoki 31 kun; yillar 365 yoki 366 kun; "bir oydan keyin" degan ibora 31-yanvar uchun aniq javobga ega emas.
Real vaziyat. Obuna xizmati har oy to'lov oladi. Dasturchi keyingi to'lov sanasini shunday hisobladi:
keyingi = oxirgi_tolov + timedelta(days=30)Bir yil ichida to'lov sanalari 5 kunga siljib ketdi. 31-yanvarda obuna bo'lganlardan esa fevralda umuman to'lov olinmadi, mayda — ikki marta. Tuzatish sifatida "oy qo'shish" funksiyasi yozildi — lekin u har safar oldingi sanadan hisoblagani uchun 31 → 28 → 28 → 28 bo'lib, mart va keyingi oylarda mijozlardan 2–3 kun erta pul yechildi.
Yana bir klassik: yoshni (bugun - tugilgan).days // 365 bilan hisoblash. 29-fevralda tug'ilgan foydalanuvchi 18 yoshga to'lmasdan "18 yosh" deb hisoblanib, cheklangan kontentga kirib ketdi.
Bu darsda datetime modulining turlarini, arifmetikasini, formatlash va tahlil qilishni hamda shunday tuzoqlarni o'rganamiz. Vaqt mintaqalari — keyingi darsda.
Bu darsda:
- To'rt asosiy tur:
date,time,datetime,timedelta - Naive va aware — qisqacha (to'liq — 15.5-dars)
- Arifmetika:
timedeltaqanday me'yorlanadi, manfiy oraliqlar - "Oy qo'shish" yo'q — va uni to'g'ri yozish
- Formatlash:
strftime, f-string,isoformat - Tahlil qilish:
strptime,fromisoformat,date.strptime(3.14) - Tuzoqlar:
datetime—datening vorisi, naive/aware solishtirish,utcnow,%y, yosh hisoblash timemoduli soatlari:time(),monotonic(),perf_counter()- Amaliy: obuna to'lovlari jadvali va ish kunlari
2. Nazariya — chuqur tushuntirish
2.1. Asosiy turlar
| Tur | Nimani bildiradi | Misol |
|---|---|---|
date |
Kalendar sanasi | date(2026, 9, 17) |
time |
Kun ichidagi vaqt | time(14, 3, 22) |
datetime |
Sana + vaqt | datetime(2026, 9, 17, 14, 3, 22) |
timedelta |
Davomiylik (oraliq) | timedelta(days=1, hours=2) |
timezone |
Qat'iy UTC siljishi | timezone(timedelta(hours=5)) |
Hammasi o'zgarmas (immutable) va xeshlanadi — dict kaliti bo'la oladi.
from datetime import date, datetime, time, timedelta, timezone
date(2026, 2, 29) # ❌ ValueError: day 29 must be in range 1..28 for month 2
date(2026, 9, 17).weekday() # 3 (dushanba = 0)
date(2026, 9, 17).isoweekday() # 4 (dushanba = 1)2.2. Naive va aware
| Naive | Aware | |
|---|---|---|
tzinfo |
None |
Bor |
| Ma'nosi | "Qaysidir mintaqadagi" vaqt | Aniq vaqt nuqtasi |
| Misol | datetime(2026, 9, 17, 14, 0) |
datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) |
Naive va aware ni < bilan solishtirish — TypeError, == bilan esa jim False. Batafsil — 15.5-darsda.
Qoida: tizim ichida aware UTC saqlang, foydalanuvchiga ko'rsatishda mahalliy vaqtga o'giring.
2.3. timedelta va arifmetika
| Amal | Natija |
|---|---|
date - date |
timedelta |
datetime - datetime |
timedelta |
date + timedelta |
date (faqat days hisobga olinadi) |
datetime + timedelta |
datetime |
timedelta * son, / son |
timedelta |
timedelta / timedelta |
float — nechta sig'adi |
timedelta // timedelta, % |
int, timedelta |
time + timedelta |
TypeError |
Ichki me'yorlash. timedelta faqat uchta maydon saqlaydi: days, seconds (0..86399), microseconds:
timedelta(days=1, hours=25, minutes=-30, seconds=3661.5)
# → timedelta(days=2, seconds=5461, microseconds=500000) "2 days, 1:31:01.500000"
timedelta(hours=-1)
# → timedelta(days=-1, seconds=82800) "-1 day, 23:00:00" td.seconds — jami soniyalar emas, faqat kun qoldig'i. Jami uchun — td.total_seconds().
timedelta da months va years yo'q — ular qat'iy uzunlikka ega emas.
2.4. Oy va yil qo'shish
"Bir oydan keyin" uchun qaror qabul qilish kerak: 31-yanvar + 1 oy = ? Keng tarqalgan qoida — oyning oxiriga qisish (clamp): 28/29-fevral.
import calendar
def oy_qosh(d: date, n: int, asl_kun: int | None = None) -> date:
oy0 = d.month - 1 + n
yil, oy = d.year + oy0 // 12, oy0 % 12 + 1
kun = min(asl_kun or d.day, calendar.monthrange(yil, oy)[1])
return d.replace(year=yil, month=oy, day=kun) Zanjir bilan hisoblash siljiydi: 31.01 → 28.02 → 28.03 → 28.04. To'g'risi — har safar asl sanadan hisoblash (yoki asl kunni saqlash): 31.01 → 28.02 → 31.03 → 30.04.
replace ham tekshiradi: datetime(2026, 1, 31).replace(month=2) → ValueError.
Murakkab kalendar qoidalari uchun tashqi kutubxona — python-dateutil (relativedelta).
2.5. Formatlash
d = datetime(2026, 9, 17, 14, 3, 22)
d.isoformat() # '2026-09-17T14:03:22' ⭐ mashina uchun
d.isoformat(timespec="minutes") # '2026-09-17T14:03'
d.strftime("%d.%m.%Y %H:%M") # '17.09.2026 14:03'
f"{d:%d.%m.%Y}" # '17.09.2026'| Kod | Ma'nosi | Kod | Ma'nosi |
|---|---|---|---|
%Y |
Yil, 4 xona | %H |
Soat 00–23 |
%y |
Yil, 2 xona | %M |
Daqiqa |
%m |
Oy 01–12 | %S |
Soniya |
%d |
Kun 01–31 | %f |
Mikrosoniya |
%j |
Yil kuni 001–366 | %z |
UTC siljishi +0500 |
%A, %B |
Hafta kuni, oy nomi | %% |
% belgisi |
%A va %B lokalga bog'liq — serverda odatda inglizcha. O'zbekcha nomlar uchun o'z lug'atingizni ishlating.
2.6. Tahlil qilish
| Usul | Qachon |
|---|---|
datetime.fromisoformat(s) |
ISO 8601 (API, baza, JSON) — tez va qat'iy |
datetime.strptime(s, format) |
Boshqa formatlar |
date.strptime(s, format) |
3.14+: to'g'ridan-to'g'ri date |
datetime.fromtimestamp(t, tz=...) |
Unix vaqtidan |
3.11 dan beri fromisoformat ISO 8601 ning deyarli barcha shakllarini tushunadi: "2026-09-17 14:03", "20260917T140322Z", "...+05:00".
strptime xulqi:
| Holat | Natija |
|---|---|
"1/2/2026", "%d/%m/%Y" |
bitta xonali ham o'tadi |
"31.02.2026" |
ValueError: day 31 must be in range... |
"17.09.2026 " (oxirida bo'shliq) |
unconverted data remains |
%y bilan "68" / "69" |
2068 / 1969 |
15.1-darsdagi regex 2026-02-30 ni o'tkazib yuborgan edi — strptime esa kalendarni biladi.
2.7. Nozik joylar
| Tuzoq | Tafsilot |
|---|---|
datetime — date ning vorisi |
isinstance(datetime(...), date) → True; lekin datetime(2026,9,17) == date(2026,9,17) → False, < → TypeError |
datetime.utcnow() |
3.12+ DeprecationWarning: naive qaytaradi. O'rniga datetime.now(UTC) |
datetime.now() |
Naive mahalliy vaqt — server mintaqasiga bog'liq |
Yosh = days // 365 |
Kabisa yillari tufayli xato |
sum(timedelta_lar) |
TypeError — sum(..., timedelta()) |
bool(time(0, 0)) |
True (3.5 dan beri) |
Yoshni to'g'ri hisoblash:
def yosh(tugilgan: date, bugun: date) -> int:
return bugun.year - tugilgan.year - ((bugun.month, bugun.day) < (tugilgan.month, tugilgan.day))2.8. time moduli soatlari
| Funksiya | Nima uchun | Xususiyati |
|---|---|---|
time.time() |
Hozirgi vaqt (Unix) | Tizim soati o'zgarsa sakraydi |
time.monotonic() |
Muddatlar, kutish | Faqat oldinga yuradi |
time.perf_counter() |
Tezlikni o'lchash | Eng aniq |
time.process_time() |
CPU vaqti | Kutish hisobga olinmaydi (14.8-dars) |
*_ns() variantlari |
Butun nanosoniyalar | Suzuvchi nuqta xatosiz |
Davomiylikni datetime.now() yoki time.time() ayirmasi bilan o'lchamang — NTP sinxronlash yoki qo'lda soat o'zgarsa, natija manfiy ham bo'lishi mumkin.
3. Tez ma'lumotnoma
from datetime import UTC, date, datetime, timedelta
hozir = datetime.now(UTC) # ⭐ aware UTC
bugun = date.today()
d = datetime.fromisoformat("2026-09-17T14:03:22+05:00")
d = datetime.strptime("17.09.2026 14:03", "%d.%m.%Y %H:%M")
f"{d:%d.%m.%Y %H:%M}", d.isoformat()
oraliq = d2 - d1; oraliq.total_seconds()
kun_soni = (date(2027, 1, 1) - bugun).days
jami = sum(oraliqlar, timedelta())Qoidalar
ichkarida aware UTC, ko'rsatishda mahalliy
td.seconds emas — td.total_seconds()
oy qo'shish — asl kundan, oy oxiriga qisib
yosh — yil farqi va (oy, kun) solishtiruvi
ISO 8601 — fromisoformat / isoformat
davomiylik — monotonic / perf_counter4. Batafsil misollar
Misol 1 — Turlar va arifmetika
"""date, time, datetime, timedelta; hafta kuni va ISO hafta; timedelta me'yorlanishi; manfiy oraliq; bo'lish va qoldiq."""
from datetime import date, datetime, time, timedelta
def main() -> None:
print("=== 1. Sana ===")
d = date(2026, 9, 17)
print(f" {d!r} → {d}")
print(f" weekday()={d.weekday()} (dushanba=0), isoweekday()={d.isoweekday()} (dushanba=1)")
print(f" isocalendar(): yil={d.isocalendar().year}, hafta={d.isocalendar().week}")
print(f" yil boshidan {d.timetuple().tm_yday}-kun")
try:
date(2026, 2, 29)
except ValueError as xato:
print(f" date(2026, 2, 29) → ValueError: {xato}")
print(f" date(2024, 2, 29) → {date(2024, 2, 29)} (kabisa yili)")
print("\n=== 2. Sana ayirmasi ===")
print(f" yil oxirigacha: {(date(2027, 1, 1) - d).days} kun")
print(f" fevral 2026: {(date(2026, 3, 1) - date(2026, 2, 1)).days} kun, fevral 2028: {(date(2028, 3, 1) - date(2028, 2, 1)).days} kun")
davr = datetime(2026, 9, 17, 14, 3) - datetime(2026, 9, 16, 15, 30)
print(f" kecha 15:30 dan bugun 14:03 gacha: {davr} ({davr.total_seconds() / 3600:.2f} soat)")
print("\n=== 3. ⭐ timedelta me'yorlanishi ===")
td = timedelta(days=1, hours=25, minutes=-30, seconds=3661.5)
print(f" kiritilgan: days=1, hours=25, minutes=-30, seconds=3661.5")
print(f" saqlangan: {td!r}")
print(f" str: {td}")
print(f" ⚠️ td.seconds={td.seconds} (faqat kun qoldig'i)")
print(f" ✅ td.total_seconds()={td.total_seconds()}")
print("\n=== 4. Manfiy oraliq ===")
manfiy = timedelta(hours=-1, minutes=-30)
print(f" {manfiy!r}")
print(f" str: {manfiy} days={manfiy.days}, seconds={manfiy.seconds}")
print(f" abs: {abs(manfiy)}, total_seconds: {manfiy.total_seconds()}")
print("\n=== 5. Oraliqlar bilan hisob ===")
dars = timedelta(minutes=45)
kun = timedelta(hours=6)
print(f" 6 soatga nechta 45 daqiqalik dars: {kun / dars} → butun: {kun // dars}, qoldiq: {kun % dars}")
print(f" 5 ta dars: {dars * 5}")
print(f" darslar yig'indisi: {sum([dars] * 5, timedelta())}")
try:
sum([dars] * 5)
except TypeError as xato:
print(f" ⚠️ sum() boshlang'ich qiymatsiz: TypeError: {xato}")
print("\n=== 6. time va combine ===")
boshlanish = time(9, 30)
print(f" {boshlanish}, {boshlanish < time(10)}")
try:
boshlanish + timedelta(minutes=45)
except TypeError:
print(" time + timedelta → TypeError")
toliq = datetime.combine(date(2026, 9, 17), boshlanish) + timedelta(minutes=45)
print(f" combine + 45 daqiqa → {toliq.time()}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Sana ===
datetime.date(2026, 9, 17) → 2026-09-17
weekday()=3 (dushanba=0), isoweekday()=4 (dushanba=1)
isocalendar(): yil=2026, hafta=38
yil boshidan 260-kun
date(2026, 2, 29) → ValueError: day 29 must be in range 1..28 for month 2 in year 2026
date(2024, 2, 29) → 2024-02-29 (kabisa yili)
=== 2. Sana ayirmasi ===
yil oxirigacha: 106 kun
fevral 2026: 28 kun, fevral 2028: 29 kun
kecha 15:30 dan bugun 14:03 gacha: 22:33:00 (22.55 soat)
=== 3. ⭐ timedelta me'yorlanishi ===
kiritilgan: days=1, hours=25, minutes=-30, seconds=3661.5
saqlangan: datetime.timedelta(days=2, seconds=5461, microseconds=500000)
str: 2 days, 1:31:01.500000
⚠️ td.seconds=5461 (faqat kun qoldig'i)
✅ td.total_seconds()=178261.5
=== 4. Manfiy oraliq ===
datetime.timedelta(days=-1, seconds=81000)
str: -1 day, 22:30:00 days=-1, seconds=81000
abs: 1:30:00, total_seconds: -5400.0
=== 5. Oraliqlar bilan hisob ===
6 soatga nechta 45 daqiqalik dars: 8.0 → butun: 8, qoldiq: 0:00:00
5 ta dars: 3:45:00
darslar yig'indisi: 3:45:00
⚠️ sum() boshlang'ich qiymatsiz: TypeError: unsupported operand type(s) for +: 'int' and 'datetime.timedelta'
=== 6. time va combine ===
09:30:00, True
time + timedelta → TypeError
combine + 45 daqiqa → 10:15:00Nima ko'rsatdi: 2.1, 2.3-bo'limlar.
Misol 2 — Formatlash va tahlil
"""isoformat va fromisoformat; strftime va f-string; strptime formatlari va xatolari; date.strptime 3.14-bob; %y tuzog'i; o'zbekcha nomlar."""
from datetime import date, datetime
OYLAR = ["yanvar", "fevral", "mart", "aprel", "may", "iyun",
"iyul", "avgust", "sentabr", "oktabr", "noyabr", "dekabr"]
KUNLAR = ["dushanba", "seshanba", "chorshanba", "payshanba", "juma", "shanba", "yakshanba"]
def ozbekcha(d: date) -> str:
return f"{d.day}-{OYLAR[d.month - 1]} {d.year}-yil, {KUNLAR[d.weekday()]}"
def main() -> None:
d = datetime(2026, 9, 17, 14, 3, 22, 500)
print("=== 1. Formatlash ===")
print(f" isoformat(): {d.isoformat()}")
print(f" isoformat(timespec='minutes'): {d.isoformat(timespec='minutes')}")
print(f" strftime('%d.%m.%Y %H:%M'): {d.strftime('%d.%m.%Y %H:%M')}")
print(f" f-string: {d:%Y/%m/%d, %j-kun}")
print(f" %A %B (lokalga bog'liq): {d:%A, %B}")
print(f" o'zbekcha: {ozbekcha(d)}")
print("\n=== 2. fromisoformat ===")
for s in ("2026-09-17", "2026-09-17T14:03:22", "2026-09-17 14:03",
"2026-09-17T14:03:22+05:00", "20260917T140322Z"):
natija = datetime.fromisoformat(s)
print(f" {s!r:29} → {natija} tzinfo={natija.tzinfo}")
try:
datetime.fromisoformat("17.09.2026")
except ValueError as xato:
print(f" '17.09.2026' → ValueError: {xato}")
print("\n=== 3. strptime ===")
for s, fmt in (("17.09.2026 14:03", "%d.%m.%Y %H:%M"),
("1/2/2026", "%d/%m/%Y"),
("2026-09-17T14:03:22+0500", "%Y-%m-%dT%H:%M:%S%z")):
print(f" {s!r:28} {fmt!r:24} → {datetime.strptime(s, fmt)}")
print(f" date.strptime 3.14-bob: {date.strptime('17.09.2026', '%d.%m.%Y')!r}")
print("\n=== 4. ⚠️ strptime xatolari ===")
for s in ("31.02.2026", "17.09.2026 ", "17-09-2026", "2026.09.17"):
try:
datetime.strptime(s, "%d.%m.%Y")
except ValueError as xato:
print(f" {s!r:14} → {xato}")
print(" ⭐ regex 2026-02-30 ni o'tkazgan edi 15.1-bob — strptime kalendarni biladi")
print("\n=== 5. ⚠️ %y — ikki xonali yil ===")
for yy in ("26", "68", "69", "99"):
print(f" '{yy}' → {datetime.strptime(yy, '%y').year}")
print(" ⭐ 1969-yilda tug'ilgan '69' — to'g'ri; 2069-yilgi shartnoma muddati — noto'g'ri")
print("\n=== 6. Foydalanuvchi kiritgan sana: bir nechta format ===")
FORMATLAR = ("%d.%m.%Y", "%d/%m/%Y", "%Y-%m-%d")
def sana_oqi(s: str) -> date | None:
s = s.strip()
for fmt in FORMATLAR:
try:
return date.strptime(s, fmt)
except ValueError:
continue
return None
for s in (" 17.09.2026", "17/09/2026", "2026-09-17", "09/17/2026", "30.02.2026"):
print(f" {s!r:14} → {sana_oqi(s)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Formatlash ===
isoformat(): 2026-09-17T14:03:22.000500
isoformat(timespec='minutes'): 2026-09-17T14:03
strftime('%d.%m.%Y %H:%M'): 17.09.2026 14:03
f-string: 2026/09/17, 260-kun
%A %B (lokalga bog'liq): Thursday, September
o'zbekcha: 17-sentabr 2026-yil, payshanba
=== 2. fromisoformat ===
'2026-09-17' → 2026-09-17 00:00:00 tzinfo=None
'2026-09-17T14:03:22' → 2026-09-17 14:03:22 tzinfo=None
'2026-09-17 14:03' → 2026-09-17 14:03:00 tzinfo=None
'2026-09-17T14:03:22+05:00' → 2026-09-17 14:03:22+05:00 tzinfo=UTC+05:00
'20260917T140322Z' → 2026-09-17 14:03:22+00:00 tzinfo=UTC
'17.09.2026' → ValueError: Invalid isoformat string: '17.09.2026'
=== 3. strptime ===
'17.09.2026 14:03' '%d.%m.%Y %H:%M' → 2026-09-17 14:03:00
'1/2/2026' '%d/%m/%Y' → 2026-02-01 00:00:00
'2026-09-17T14:03:22+0500' '%Y-%m-%dT%H:%M:%S%z' → 2026-09-17 14:03:22+05:00
date.strptime 3.14-bob: datetime.date(2026, 9, 17)
=== 4. ⚠️ strptime xatolari ===
'31.02.2026' → day 31 must be in range 1..28 for month 2 in year 2026
'17.09.2026 ' → unconverted data remains:
'17-09-2026' → time data '17-09-2026' does not match format '%d.%m.%Y'
'2026.09.17' → time data '2026.09.17' does not match format '%d.%m.%Y'
⭐ regex 2026-02-30 ni o'tkazgan edi 15.1-bob — strptime kalendarni biladi
=== 5. ⚠️ %y — ikki xonali yil ===
'26' → 2026
'68' → 2068
'69' → 1969
'99' → 1999
⭐ 1969-yilda tug'ilgan '69' — to'g'ri; 2069-yilgi shartnoma muddati — noto'g'ri
=== 6. Foydalanuvchi kiritgan sana: bir nechta format ===
' 17.09.2026' → 2026-09-17
'17/09/2026' → 2026-09-17
'2026-09-17' → 2026-09-17
'09/17/2026' → None
'30.02.2026' → NoneNima ko'rsatdi: 2.5, 2.6-bo'limlar.
Misol 3 — Tuzoqlar
"""Oy qo'shish: zanjir va asl kun; yosh hisoblash; datetime va date merosi; naive va aware solishtirish; utcnow; monotonic soat."""
import calendar
import time
import warnings
from datetime import UTC, date, datetime, timedelta, timezone
def oy_qosh(d: date, n: int, asl_kun: int | None = None) -> date:
oy0 = d.month - 1 + n
yil, oy = d.year + oy0 // 12, oy0 % 12 + 1
kun = min(asl_kun or d.day, calendar.monthrange(yil, oy)[1])
return d.replace(year=yil, month=oy, day=kun)
def yosh(tugilgan: date, bugun: date) -> int:
return bugun.year - tugilgan.year - ((bugun.month, bugun.day) < (tugilgan.month, tugilgan.day))
def main() -> None:
boshi = date(2026, 1, 31)
print("=== 1. ⚠️ '30 kun' — 'bir oy' emas ===")
sanalar = [boshi + timedelta(days=30 * i) for i in range(13)]
print(f" 12 marta +30 kun: {sanalar[-1]} (bir yildan keyin kutilgan: 2027-01-31)")
print(f" siljish: {(date(2027, 1, 31) - sanalar[-1]).days} kun")
print("\n=== 2. ⚠️ Oy qo'shish: zanjir va asl sana ===")
zanjir = [boshi]
for _ in range(4):
zanjir.append(oy_qosh(zanjir[-1], 1))
asldan = [oy_qosh(boshi, i) for i in range(5)]
print(f" zanjir: {[f'{d:%d.%m}' for d in zanjir]}")
print(f" asl sanadan: {[f'{d:%d.%m}' for d in asldan]}")
print(f" kabisa yili: {oy_qosh(date(2028, 1, 31), 1)}, orqaga: {oy_qosh(boshi, -2)}")
try:
datetime(2026, 1, 31).replace(month=2)
except ValueError as xato:
print(f" replace(month=2) → ValueError: {xato}")
print("\n=== 3. ⚠️ Yosh hisoblash (29-fevralda tug'ilgan) ===")
tugilgan = date(2008, 2, 29)
for bugun in (date(2026, 2, 28), date(2026, 3, 1)):
xato_usul = (bugun - tugilgan).days // 365
print(f" {bugun}: days//365 = {xato_usul}, to'g'ri = {yosh(tugilgan, bugun)}")
print("\n=== 4. ⚠️ datetime — date ning vorisi ===")
dt, d = datetime(2026, 9, 17), date(2026, 9, 17)
print(f" isinstance(datetime, date): {isinstance(dt, date)}")
print(f" datetime(2026,9,17) == date(2026,9,17): {dt == d}")
try:
d < datetime(2026, 9, 18)
except TypeError as xato:
print(f" date < datetime → TypeError: {xato}")
print(f" lug'at kaliti: {{date: ...}}.get(datetime) → {({d: 'topildi'}).get(dt)}")
print(f" ✅ .date() bilan: {dt.date() == d}")
print("\n=== 5. ⚠️ Naive va aware ===")
naive = datetime(2026, 9, 17, 12, 0)
aware = datetime(2026, 9, 17, 12, 0, tzinfo=UTC)
print(f" naive == aware: {naive == aware} ← jim False")
try:
naive < aware
except TypeError as xato:
print(f" naive < aware → TypeError: {xato}")
toshkent = aware.astimezone(timezone(timedelta(hours=5)))
print(f" bir vaqt nuqtasi: {aware} == {toshkent} → {aware == toshkent}")
print("\n=== 6. ⚠️ utcnow() eskirgan ===")
with warnings.catch_warnings(record=True) as ogoh:
warnings.simplefilter("always")
eski = datetime.utcnow()
print(f" {ogoh[0].category.__name__}: tzinfo={eski.tzinfo}")
print(f" ✅ datetime.now(UTC).tzinfo = {datetime.now(UTC).tzinfo}")
print("\n=== 7. Davomiylikni o'lchash ===")
bosh_m, bosh_p = time.monotonic(), time.perf_counter()
time.sleep(0.05)
print(f" monotonic ayirmasi 0.05 s dan katta: {time.monotonic() - bosh_m >= 0.05}")
print(f" perf_counter ayirmasi 0.05 s dan katta: {time.perf_counter() - bosh_p >= 0.05}")
print(f" time.monotonic hech qachon orqaga yurmaydi: {time.get_clock_info('monotonic').monotonic}")
print(f" time.time esa sozlanadi: {time.get_clock_info('time').adjustable}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ⚠️ '30 kun' — 'bir oy' emas ===
12 marta +30 kun: 2027-01-26 (bir yildan keyin kutilgan: 2027-01-31)
siljish: 5 kun
=== 2. ⚠️ Oy qo'shish: zanjir va asl sana ===
zanjir: ['31.01', '28.02', '28.03', '28.04', '28.05']
asl sanadan: ['31.01', '28.02', '31.03', '30.04', '31.05']
kabisa yili: 2028-02-29, orqaga: 2025-11-30
replace(month=2) → ValueError: day 31 must be in range 1..28 for month 2 in year 2026
=== 3. ⚠️ Yosh hisoblash (29-fevralda tug'ilgan) ===
2026-02-28: days//365 = 18, to'g'ri = 17
2026-03-01: days//365 = 18, to'g'ri = 18
=== 4. ⚠️ datetime — date ning vorisi ===
isinstance(datetime, date): True
datetime(2026,9,17) == date(2026,9,17): False
date < datetime → TypeError: '<' not supported between instances of 'datetime.date' and 'datetime.datetime'
lug'at kaliti: {date: ...}.get(datetime) → None
✅ .date() bilan: True
=== 5. ⚠️ Naive va aware ===
naive == aware: False ← jim False
naive < aware → TypeError: can't compare offset-naive and offset-aware datetimes
bir vaqt nuqtasi: 2026-09-17 12:00:00+00:00 == 2026-09-17 17:00:00+05:00 → True
=== 6. ⚠️ utcnow() eskirgan ===
DeprecationWarning: tzinfo=None
✅ datetime.now(UTC).tzinfo = UTC
=== 7. Davomiylikni o'lchash ===
monotonic ayirmasi 0.05 s dan katta: True
perf_counter ayirmasi 0.05 s dan katta: True
time.monotonic hech qachon orqaga yurmaydi: True
time.time esa sozlanadi: TrueNima ko'rsatdi: 2.2, 2.4, 2.7, 2.8-bo'limlar.
Misol 4 — Amaliy: obuna to'lovlari va ish kunlari
Kirishdagi vaziyatni to'g'ri hal qilamiz. Obuna asl sana bo'yicha oyma-oy yangilanadi (oy oxiriga qisib), to'lov sanasi dam olish kuniga tushsa — keyingi ish kuniga suriladi, to'lov o'tmasa — 3 ish kuni imtiyoz beriladi. Qat'iy bayram sanalari kodda, harakatlanuvchi bayramlar (hayitlar) esa har yili rasmiy e'lon qilingani uchun ma'lumot sifatida tashqaridan beriladi.
"""Asl sanadan oy qo'shish; dam olish va bayramlarni hisobga olgan ish kunlari; imtiyoz davri; yil davomidagi to'lovlar jadvali va tekshiruvlar."""
import calendar
from dataclasses import dataclass
from datetime import date, timedelta
QATIY_BAYRAMLAR = {(1, 1), (3, 8), (3, 21), (5, 9), (9, 1), (10, 1), (12, 8)}
def oy_qosh(d: date, n: int, asl_kun: int) -> date:
oy0 = d.month - 1 + n
yil, oy = d.year + oy0 // 12, oy0 % 12 + 1
return date(yil, oy, min(asl_kun, calendar.monthrange(yil, oy)[1]))
@dataclass(frozen=True, slots=True)
class Kalendar:
qoshimcha_bayramlar: frozenset[date] = frozenset()
def ish_kunimi(self, d: date) -> bool:
return (d.weekday() < 5
and (d.month, d.day) not in QATIY_BAYRAMLAR
and d not in self.qoshimcha_bayramlar)
def keyingi_ish_kuni(self, d: date) -> date:
while not self.ish_kunimi(d):
d += timedelta(days=1)
return d
def ish_kuni_qosh(self, d: date, n: int) -> date:
while n > 0:
d += timedelta(days=1)
if self.ish_kunimi(d):
n -= 1
return d
@dataclass(frozen=True, slots=True)
class Tolov:
davr: int
reja: date
haqiqiy: date
imtiyoz_oxiri: date
def jadval(obuna_sanasi: date, oylar: int, kal: Kalendar) -> list[Tolov]:
natija = []
for i in range(1, oylar + 1):
reja = oy_qosh(obuna_sanasi, i, obuna_sanasi.day)
haqiqiy = kal.keyingi_ish_kuni(reja)
natija.append(Tolov(i, reja, haqiqiy, kal.ish_kuni_qosh(haqiqiy, 3)))
return natija
def main() -> None:
# Harakatlanuvchi bayramlar har yili rasmiy e'lon qilinadi — bu yerda namuna sifatida berilgan
kal = Kalendar(qoshimcha_bayramlar=frozenset({date(2026, 3, 20), date(2026, 5, 27)}))
obuna = date(2026, 1, 31)
tolovlar = jadval(obuna, 12, kal)
print(f"=== 1. Obuna: {obuna:%d.%m.%Y}, 12 oylik jadval ===")
sarlavha = ("davr", "reja", "kun", "to'lov", "imtiyoz oxiri")
print(f" {sarlavha[0]:>4} {sarlavha[1]:10} {sarlavha[2]:9} {sarlavha[3]:10} {sarlavha[4]}")
for t in tolovlar:
kun = ["du", "se", "chor", "pay", "ju", "shan", "yak"][t.reja.weekday()]
surildi = " ←" if t.haqiqiy != t.reja else ""
print(f" {t.davr:>4} {t.reja:%d.%m.%Y} {kun:9} {t.haqiqiy:%d.%m.%Y} {t.imtiyoz_oxiri:%d.%m.%Y}{surildi}")
print("\n=== 2. Tekshiruvlar ===")
print(f" har oy aynan bitta to'lov: {len({(t.reja.year, t.reja.month) for t in tolovlar}) == 12}")
print(f" reja sanalari asl kundan siljimadi (31 yoki oy oxiri): "
f"{all(t.reja.day == min(31, calendar.monthrange(t.reja.year, t.reja.month)[1]) for t in tolovlar)}")
print(f" hamma to'lovlar ish kunida: {all(kal.ish_kunimi(t.haqiqiy) for t in tolovlar)}")
print(f" imtiyoz doim 3 ish kuni: "
f"{all(sum(kal.ish_kunimi(t.haqiqiy + timedelta(days=k)) for k in range(1, (t.imtiyoz_oxiri - t.haqiqiy).days + 1)) == 3 for t in tolovlar)}")
surilganlar = [t for t in tolovlar if t.haqiqiy != t.reja]
print(f" surilgan to'lovlar: {len(surilganlar)} ta")
print("\n=== 3. Noto'g'ri usul bilan solishtirish ===")
xato = [obuna + timedelta(days=30 * i) for i in range(1, 13)]
ikki_marta = [oy for oy in range(1, 13) if sum(d.month == oy and d.year == 2026 for d in xato) == 2]
otkazilgan = [oy for oy in range(2, 13) if not any(d.month == oy and d.year == 2026 for d in xato)]
print(f" +30 kun: oxirgi to'lov {xato[-1]:%d.%m.%Y}, to'g'risi {tolovlar[-1].reja:%d.%m.%Y}")
print(f" ikki marta to'lov olingan oylar: {ikki_marta}")
print(f" to'lovsiz qolgan oylar: {otkazilgan}")
print("\n=== 4. Bayram atrofida ish kunlari ===")
for d in (date(2026, 3, 19), date(2026, 12, 31)):
print(f" {d:%d.%m.%Y} + 3 ish kuni → {kal.ish_kuni_qosh(d, 3):%d.%m.%Y}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Obuna: 31.01.2026, 12 oylik jadval ===
davr reja kun to'lov imtiyoz oxiri
1 28.02.2026 shan 02.03.2026 05.03.2026 ←
2 31.03.2026 se 31.03.2026 03.04.2026
3 30.04.2026 pay 30.04.2026 05.05.2026
4 31.05.2026 yak 01.06.2026 04.06.2026 ←
5 30.06.2026 se 30.06.2026 03.07.2026
6 31.07.2026 ju 31.07.2026 05.08.2026
7 31.08.2026 du 31.08.2026 04.09.2026
8 30.09.2026 chor 30.09.2026 06.10.2026
9 31.10.2026 shan 02.11.2026 05.11.2026 ←
10 30.11.2026 du 30.11.2026 03.12.2026
11 31.12.2026 pay 31.12.2026 06.01.2027
12 31.01.2027 yak 01.02.2027 04.02.2027 ←
=== 2. Tekshiruvlar ===
har oy aynan bitta to'lov: True
reja sanalari asl kundan siljimadi (31 yoki oy oxiri): True
hamma to'lovlar ish kunida: True
imtiyoz doim 3 ish kuni: True
surilgan to'lovlar: 4 ta
=== 3. Noto'g'ri usul bilan solishtirish ===
+30 kun: oxirgi to'lov 26.01.2027, to'g'risi 31.01.2027
ikki marta to'lov olingan oylar: [5]
to'lovsiz qolgan oylar: [2]
=== 4. Bayram atrofida ish kunlari ===
19.03.2026 + 3 ish kuni → 25.03.2026
31.12.2026 + 3 ish kuni → 06.01.2027Nima ko'rsatdi: 2.3, 2.4-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Bir oy = 30 kun" | Oylar 28–31 kun; "oy qo'shish" alohida qoida talab qiladi |
"td.seconds — jami soniyalar" |
Faqat kun qoldig'i; jami — total_seconds() |
"timedelta(months=1) bor" |
Yo'q — TypeError |
"datetime.now() — universal vaqt" |
Naive, server mintaqasidagi vaqt |
"utcnow() aware UTC qaytaradi" |
Naive qaytaradi, 3.12+ eskirgan |
"datetime == date sana bir xil bo'lsa True" |
Doim False |
| "Yosh = kunlar // 365" | Kabisa yillari tufayli xato |
"Davomiylik = time.time() ayirmasi" |
monotonic yoki perf_counter |
6. Keng tarqalgan xatolar va yechimlari
1. Oyni kunlar bilan qo'shish
keyingi = sana + timedelta(days=30) # ❌
keyingi = oy_qosh(asl_sana, n, asl_sana.day) # ✅2. td.seconds dan foydalanish
soat = (tugash - boshlanish).seconds / 3600 # ❌ 1 kundan uzunida xato
soat = (tugash - boshlanish).total_seconds() / 3600 # ✅3. Naive vaqt saqlash
yaratilgan = datetime.now() # ❌
yaratilgan = datetime.now(UTC) # ✅4. utcnow
datetime.utcnow() # ❌ naive, eskirgan
datetime.now(UTC) # ✅5. Sanani regex bilan tekshirish
re.fullmatch(r"\d{2}\.\d{2}\.\d{4}", s) # ⚠️ 31.02.2026 o'tadi
datetime.strptime(s, "%d.%m.%Y") # ✅6. Sana va vaqtni aralashtirish
if yozuv.yaratilgan == date.today(): ... # ❌ datetime == date → False
if yozuv.yaratilgan.date() == date.today(): ... # ✅7. Ikki xonali yil
datetime.strptime("01.01.69", "%d.%m.%y") # ⚠️ 1969
# ✅ foydalanuvchidan 4 xonali yil so'rang8. Davomiylikni devor soati bilan o'lchash
bosh = time.time(); ish(); davom = time.time() - bosh # ❌
bosh = time.monotonic(); ish(); davom = time.monotonic() - bosh # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 15.1–15.3-darslar (o'tilgan): sanalarni matndan ajratish
- 15.5-dars: vaqt mintaqalari,
zoneinfo, yozgi vaqt - 15.16-dars:
logging— vaqt belgilari - 16.2-dars:
jsonda sanalarni saqlash (ISO 8601) - 16.7-dars:
sqlite3— sana ustunlari - 17-qism: vaqtga bog'liq kodni testlash (vaqtni "muzlatish")
- 23-qism: PostgreSQL
timestamptz - 24-qism:
pandasvaqt qatorlari
8. Eng yaxshi amaliyotlar
Tizim ichida aware UTC, foydalanuvchiga mahalliy vaqt.
Almashinuv formati — ISO 8601 (
isoformat/fromisoformat).Oy va yil arifmetikasi uchun aniq qoida yozing va hujjatlashtiring — qisish, asl kun.
Yosh va yilliklarni kunlar bilan emas, kalendar maydonlari bilan hisoblang.
total_seconds()ishlating,secondsemas.Davomiylik —
monotonic/perf_counter.Foydalanuvchi sanasini
strptimebilan tahlil qiling — bir nechta ruxsat etilgan format bilan.Joriy vaqtni funksiyaga parametr sifatida bering (
bugun: date) — kod testlanadigan bo'ladi.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
from datetime import date, datetime, timedelta
1. print(date(2026, 9, 17).weekday())
2. print((date(2026, 3, 1) - date(2026, 2, 1)).days)
3. print(timedelta(hours=25))
4. print(timedelta(hours=25).seconds)
5. print(timedelta(hours=-1))
6. print(date(2026, 12, 31) + timedelta(days=1))
7. print(timedelta(hours=3) // timedelta(minutes=40))
8. print(datetime(2026, 9, 17) == date(2026, 9, 17))
9. print(datetime.strptime("5/3/2026", "%d/%m/%Y").month)
10. print(datetime.fromisoformat("2026-09-17 14:03").minute)
11. print(f"{date(2026, 1, 5):%d.%m.%y}")
12. print(datetime.strptime("69", "%y").year)Javoblar
3— payshanba (dushanba = 0)281 day, 1:00:003600-1 day, 23:00:002027-01-014False3305.01.261969
Vazifa 2: Xatolarni tuzating
1. def soatlar(boshlanish, tugash):
return (tugash - boshlanish).seconds / 3600
2. def keyingi_oy(sana):
return sana.replace(month=sana.month + 1)
3. def yosh(tugilgan):
return (date.today() - tugilgan).days // 365
4. def bugungimi(yozuv_vaqti):
return yozuv_vaqti == date.today() # yozuv_vaqti — datetime
5. def yaratish_vaqti():
return datetime.utcnow().isoformat()Javoblar
1. def soatlar(boshlanish, tugash):
return (tugash - boshlanish).total_seconds() / 3600
2. def keyingi_oy(sana, asl_kun=None):
oy0 = sana.month # 12-oy → keyingi yil
yil, oy = sana.year + oy0 // 12, oy0 % 12 + 1
kun = min(asl_kun or sana.day, calendar.monthrange(yil, oy)[1])
return sana.replace(year=yil, month=oy, day=kun)
3. def yosh(tugilgan, bugun): # bugun — parametr
return bugun.year - tugilgan.year - ((bugun.month, bugun.day) < (tugilgan.month, tugilgan.day))
4. def bugungimi(yozuv_vaqti, bugun):
return yozuv_vaqti.date() == bugun
5. def yaratish_vaqti():
return datetime.now(UTC).isoformat()Vazifa 3: Kalendar chop etuvchi
oy_kalendari(yil, oy) funksiyasini yozing:
- Dushanbadan boshlanadigan jadval (o'zbekcha kun nomlari:
Du Se Ch Pa Ju Sh Ya) - Bugungi kun
[17]ko'rinishida belgilansin (bugunparametr orqali) - Qat'iy bayramlar
*bilan calendarmodulisiz, faqatdatevatimedeltabilan- Natijani
calendar.TextCalendarbilan solishtiring
Vazifa 4: Nisbiy vaqt
nisbiy(vaqt, hozir) → "hozirgina", "5 daqiqa oldin", "kecha 14:03", "3 kun oldin", "17-sentabr", "2025-yil 3-mart":
- Kelajak uchun ham:
"2 soatdan keyin","ertaga 09:00" - "Kecha" va "ertaga" — kalendar kuniga qarab (24 soatga emas)
- O'zbekcha oy nomlari
- 20 ta chegara holati bilan sinang (yarim tun, yil almashishi)
Vazifa 5: Ish vaqti hisoblagichi
Xodimning kirish-chiqish yozuvlari ("2026-09-17 08:55 kirdi", "... 18:10 chiqdi"):
- Kunlik ishlagan vaqt —
timedelta - Tushlik (13:00–14:00) ichiga tushgan vaqt ayirilsin
- 9:00 dan kechikishlar va 18:00 dan keyingi qo'shimcha vaqt
- Tungi smena (22:00 → 06:00) to'g'ri hisoblansin
- Oylik hisobot: jami soat, kechikishlar soni, qo'shimcha soat
Vazifa 6: Muddatlar kalkulyatori
ish_kuni_qosh(sana, n)— manfiynbilan hamish_kunlari_orasida(a, b)— ikki sana orasidagi ish kunlari soni, tsiklsiz formula bilan (haftalar soni × 5 + qoldiq)- Tsiklli va formulali variant natijasi 1000 ta tasodifiy juftlikda bir xil ekanini tekshiring
- Bayramlarni fayldan o'qing
Vazifa 7: O'ylash
Python datetime modulida timedelta faqat kun, soniya va mikrosoniyani biladi, "oy" va "yil" esa yo'q. PostgreSQL'da esa interval '1 month' bor, Java'da Period (kalendar) va Duration (vaqt) alohida turlar. Nega "davomiylik" ikki xil tushuncha va Python dizayni qanday kelishuvga borgan?
Javob
Qisqa javob: "Davomiylik" ikki xil narsa: fizik vaqt (aniq soniyalar soni — Duration) va kalendar oralig'i (oy, yil — Period), uzunligi qaysi sanaga qo'shilganiga bog'liq. Python faqat birinchisini standart kutubxonaga kiritgan: u aniq, solishtiriladigan va arifmetik jihatdan izchil. Kalendar oralig'i esa qoidalar talab qiladi (31-yanvar + 1 oy?) — ular dateutil.relativedelta kabi tashqi kutubxonalarga qoldirilgan.
1. Ikki xil tushuncha
| Fizik davomiylik | Kalendar oralig'i | |
|---|---|---|
| Misol | 90 daqiqa, 3 kun (72 soat) | 1 oy, 1 yil |
| Uzunligi | Qat'iy | Sanaga bog'liq (28–31 kun) |
| Solishtirish | Doim mumkin | 1 oy va 30 kun — qaysi katta? |
| Qo'shish | Kommutativ, assotsiativ | (31.01 + 1 oy) + 1 oy ≠ 31.01 + 2 oy |
| Python | timedelta |
Yo'q (dateutil.relativedelta) |
| Java | Duration |
Period |
2. Kalendar arifmetikasining muammolari
- Qisish: 31-yanvar + 1 oy = 28-fevral? 3-mart?
- Assotsiativ emas: zanjir va to'g'ridan-to'g'ri hisob har xil (Misol 3)
- Qaytuvchan emas:
31.01 + 1 oy - 1 oy = 28.01 - Solishtirib bo'lmaydi:
interval '1 month' > interval '30 days'— PostgreSQL buni 30 kunlik oy deb qabul qilib hal qiladi, bu ham kelishuv
3. Python dizayni
timedelta— algebraik jihatdan "yaxshi" tur: qo'shish, ayirish, ko'paytirish, bo'lish, solishtirish, xesh- Kalendar qoidalari biznesga bog'liq (bank, sug'urta, obuna har xil qisish qoidasini ishlatadi) — standart kutubxona bitta qoidani majburlamaydi
- Tashqi kutubxona:
relativedelta(months=+1)— oy oxiriga qisish bilan
4. Boshqa tillar
| Til/tizim | Yondashuv |
|---|---|
Java (java.time) |
Duration va Period alohida — eng aniq dizayn |
| PostgreSQL | Bitta interval: oy, kun va mikrosoniya alohida maydonlar |
JavaScript (Temporal) |
Duration ichida yil/oy/kun/soat, hisoblashda relativeTo sana talab qilinadi |
| .NET | TimeSpan (fizik), oy uchun AddMonths metodi |
| Python | timedelta + dateutil.relativedelta |
5. Amaliy xulosa
- "Davomiylik" deganda avval qaysi turdagi ekanini aniqlang
- Obuna, shartnoma, kredit — kalendar oralig'i; aniq qoida yozing va hujjatlashtiring
- Taymer, muddat, SLA — fizik davomiylik;
timedeltava aware UTC - Kalendar oralig'ini doim asl sanadan hisoblang
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda sana va vaqt bilan ishlashning asoslarini va tuzoqlarini o'rgandik.
Eng muhim uch fikr:
timedelta— fizik davomiylik, oy emas. U faqat kun, soniya va mikrosoniyani saqlaydi va avtomatik me'yorlanadi:timedelta(hours=-1)—-1 day, 23:00:00,td.secondsesa jami emas, faqat kun qoldig'i (total_seconds()kerak). "Bir oy" uchun alohida qoida yoziladi: oy oxiriga qisish va har safar asl sanadan hisoblash — aks holda 31 → 28 → 28 bo'lib siljiydi. Yosh ham kunlar bilan emas, kalendar maydonlari bilan hisoblanadi.Formatlash va tahlil: ISO 8601 va
strptime. Mashinalar orasida —isoformat()/fromisoformat(), odamlar uchun —strftimeyoki f-string va o'zbekcha nomlar lug'ati (%A,%Blokalga bog'liq).strptimekalendarni biladi —31.02.2026ni rad etadi, regex esa yo'q; 3.14 dadate.strptimeto'g'ridan-to'g'ri sana qaytaradi.%yesa69ni 1969 deb o'qiydi.Jim tuzoqlar.
datetime—datening vorisi, lekindatetime == datedoimFalse; naive va aware==bilanFalse,<bilanTypeError;utcnow()naive qaytaradi va eskirgan — o'rnigadatetime.now(UTC). Davomiylik esa devor soati bilan emas,monotonic()yokiperf_counter()bilan o'lchanadi.
Keyingi darsda vaqt mintaqalariga o'tamiz: zoneinfo, yozgi vaqtga o'tish kunlaridagi "mavjud bo'lmagan" va "ikki marta takrorlanadigan" soatlar, UTC da saqlash va mahalliy vaqtda ko'rsatish.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!