Sana va vaqt — date(), DateTime, timezone
Muammodan boshlaylik
Saytingiz serveri Germaniyada. Toshkentdagi foydalanuvchi soat 14:00 da buyurtma berdi, lekin bazada 09:00 yozildi. Hisobotda "bugungi buyurtmalar" ro'yxatiga kechqurun 19:30 dagi buyurtmalar tushmayapti. Obuna "30 kundan keyin tugaydi" deb hisoblangan, lekin fevralda noto'g'ri sana chiqdi.
Sana va vaqt — dasturlashdagi eng ko'p xato chiqadigan mavzulardan biri. Sababi: vaqt mintaqalari, oy uzunliklari, kabisa yillar. PHP bu murakkablikni o'z zimmasiga oladi — agar to'g'ri vositalardan foydalansangiz.
Timestamp — vaqtning asosi
Kompyuter uchun vaqt — bitta son: 1970-yil 1-yanvar 00:00 UTC dan beri o'tgan soniyalar. Bu Unix timestamp deyiladi.
<?php
echo time(); // 1793631313 — hozirgi lahza
Timestamp vaqt mintaqasiga bog'liq emas — Toshkentda ham, Nyu-Yorkda ham bir lahzada bir xil son.
date() — formatlash
<?php
echo date('Y-m-d'); // 2026-11-02
echo date('d.m.Y H:i'); // 02.11.2026 14:30
echo date('Y-m-d H:i:s'); // 2026-11-02 14:30:05 — bazaga yozish formati
echo date('d.m.Y', 0); // 01.01.1970 — ikkinchi parametr: timestamp
| Belgi | Ma'nosi | Misol |
|---|---|---|
Y |
Yil, 4 raqam | 2026 |
m |
Oy, 2 raqam | 03 |
n |
Oy, nolsiz | 3 |
d |
Kun, 2 raqam | 07 |
j |
Kun, nolsiz | 7 |
H |
Soat (24) | 14 |
i |
Daqiqa | 05 |
s |
Soniya | 09 |
N |
Hafta kuni (1=dushanba, 7=yakshanba) | 1 |
t |
Oydagi kunlar soni | 30 |
Vaqt mintaqasi — eng muhim sozlama
<?php
echo date_default_timezone_get(); // UTC — ko'p serverlarda standart
echo date('H:i'); // 09:30 — Toshkentda esa 14:30!
Skript boshida mintaqani belgilang:
<?php
date_default_timezone_set('Asia/Tashkent');
echo date('H:i'); // 14:30
Yoki php.ini da: date.timezone = Asia/Tashkent.
[!TIP] Katta loyihalardagi qoida: bazada va serverda hammasi UTC, foydalanuvchiga ko'rsatishda — uning mintaqasiga o'giriladi. Shunda turli mamlakatlardagi foydalanuvchilar va serverlar chalkashmaydi. Faqat O'zbekiston uchun kichik sayt bo'lsa,
Asia/Tashkentni hamma joyda ishlatish ham normal.
DateTimeImmutable — zamonaviy usul
date() va time() oddiy holatlar uchun yaxshi. Sana bilan hisob-kitob uchun esa ob'ektlar ishlatiladi:
<?php
$hozir = new DateTimeImmutable();
echo $hozir->format('d.m.Y H:i');
$sana = new DateTimeImmutable('2026-03-15 10:00');
$tugilgan = new DateTimeImmutable('1998-07-21');
$ertaga = new DateTimeImmutable('tomorrow');
$keyingiDushanba = new DateTimeImmutable('next monday');
Qo'shish va ayirish
<?php
$bugun = new DateTimeImmutable('2026-01-31');
echo $bugun->modify('+1 day')->format('Y-m-d'); // 2026-02-01
echo $bugun->modify('+30 days')->format('Y-m-d'); // 2026-03-02
echo $bugun->modify('-1 week')->format('Y-m-d'); // 2026-01-24
echo $bugun->add(new DateInterval('P1M'))->format('Y-m-d'); // 2026-03-03 ?!
Oxirgisi g'alati: 31-yanvar + 1 oy = 31-fevral, bunday kun yo'q, PHP uni 3-martga "toshirib" yuboradi. Oyning oxirgi kuni kerak bo'lsa:
<?php
echo $bugun->modify('last day of next month')->format('Y-m-d'); // 2026-02-28
Nima uchun Immutable?
<?php
// DateTime (o'zgaruvchan) — tuzoq
$boshlanish = new DateTime('2026-01-01');
$tugash = $boshlanish->modify('+30 days');
echo $boshlanish->format('Y-m-d'); // 2026-01-31 ← boshlanish ham o'zgarib ketdi!
// DateTimeImmutable — xavfsiz
$boshlanish = new DateTimeImmutable('2026-01-01');
$tugash = $boshlanish->modify('+30 days');
echo $boshlanish->format('Y-m-d'); // 2026-01-01 ← o'zgarmadi
DateTime ning metodlari ob'ektning o'zini o'zgartiradi. DateTimeImmutable esa yangi ob'ekt qaytaradi. Doim DateTimeImmutable ni ishlating.
Ikki sana orasidagi farq
<?php
$tugilgan = new DateTimeImmutable('1998-07-21');
$bugun = new DateTimeImmutable('today');
$farq = $tugilgan->diff($bugun);
echo $farq->y; // 28 — to'liq yillar (yosh)
echo $farq->m; // 3 — qolgan oylar
echo $farq->d; // 12 — qolgan kunlar
echo $farq->days; // 10331 — jami kunlar
Obuna qolgan kunlari:
<?php
$tugash = new DateTimeImmutable('2026-12-01');
$qoldi = (new DateTimeImmutable('today'))->diff($tugash);
if ($qoldi->invert) {
echo "Obuna tugagan";
} else {
echo "Obuna tugashiga {$qoldi->days} kun qoldi";
}
invert — 1 bo'lsa, ikkinchi sana birinchisidan oldin (ya'ni muddat o'tib ketgan).
Foydalanuvchi kiritgan sanani tekshirish
<?php
$kiritilgan = $_POST['sana'] ?? ''; // "2026-02-30"
$sana = DateTimeImmutable::createFromFormat('!Y-m-d', $kiritilgan);
$xatolar = DateTimeImmutable::getLastErrors();
if ($sana === false || ($xatolar && ($xatolar['warning_count'] || $xatolar['error_count']))) {
echo "Sana noto'g'ri";
} else {
echo $sana->format('d.m.Y');
}
createFromFormat aniq formatni kutadi. ! — vaqtni 00:00:00 ga tushiradi. Ogohlantirishlar ham tekshiriladi, chunki aks holda 2026-02-30 jimgina 2026-03-02 ga aylanadi.
Mintaqalar orasida o'girish
<?php
$utc = new DateTimeImmutable('2026-11-02 09:30:00', new DateTimeZone('UTC'));
$toshkent = $utc->setTimezone(new DateTimeZone('Asia/Tashkent'));
echo $toshkent->format('H:i'); // 14:30
$nyuYork = $utc->setTimezone(new DateTimeZone('America/New_York'));
echo $nyuYork->format('H:i'); // 04:30
O'zbekcha oy nomlari
date('F') inglizcha nom beradi (November). O'zbekcha uchun oddiy massiv yetarli:
<?php
function sanaUz(DateTimeInterface $sana): string
{
$oylar = [1 => 'yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun',
'iyul', 'avgust', 'sentabr', 'oktabr', 'noyabr', 'dekabr'];
return $sana->format('j') . '-' . $oylar[(int) $sana->format('n')] . ', ' . $sana->format('Y');
}
echo sanaUz(new DateTimeImmutable('2026-11-02')); // 2-noyabr, 2026
Kengaytirilgan variant — intl kengaytmasidagi IntlDateFormatter (uz_Latn lokali).
Nima uchun shunday?
Nima uchun vaqt 1970-yildan hisoblanadi?
Unix operatsion tizimi 1970-yillar boshida yaratilgan. Ishlab chiquvchilar "yaqin, yumaloq sana" sifatida 1970-yil 1-yanvarni tanlashgan. 32-bitli tizimlarda bu son 2038-yil 19-yanvarda to'lib qoladi ("2038-yil muammosi") — xuddi 2000-yil muammosi kabi. 64-bitli PHP da bu muammo yo'q: chegara milliardlab yil keyin.
Xulosa
Eslab qoling:
date_default_timezone_set('Asia/Tashkent')— yokiphp.inida; bu birinchi ishdate('Y-m-d H:i:s')— formatlash;time()— joriy timestamp- Hisob-kitob uchun
DateTimeImmutable—DateTimeemas ->modify('+30 days'),->diff(),->setTimezone()- Foydalanuvchi sanasini
createFromFormat+getLastErrors()bilan tekshiring - "+1 month" oy oxirida kutilmagan natija beradi —
last day of next month
Keyingi dars
27-dars: Xatolar — try/catch/finally, Exception, error_reporting