PHP / Огноо ба цаг

Огноо ба цаг

Захиалга хэзээ хийгдсэн, хэрэглэгч сүүлд хэзээ нэвтэрсэн, хэдэн хоногийн дараа хугацаа дуусах — вэб апп-д огноо, цаг байнга хэрэглэгддэг. PHP-д date(), strtotime(), DateTime, DateTimeImmutable зэрэг хүчирхэг хэрэгсэл байдаг. Улаанбаатарын цагийн бүс (Asia/Ulaanbaatar) онцгой анхаарал шаардагддаг тул тусад нь авч үзнэ.

Цагийн бүс тохируулах

PHP-д цагийн бүсийг зөв тохируулах нь хамгийн эхний алхам юм. Тохируулаагүй бол серверийн цаг ашиглагдах бөгөөд энэ нь буруу үр дүн өгч болно:

php
<?php
// Файлын эхэнд эсвэл php.ini-д тохируулна
date_default_timezone_set('Asia/Ulaanbaatar');

// Одоогийн цагийн бүс шалгах
echo date_default_timezone_get();   // Asia/Ulaanbaatar

// Unix timestamp — 1970-01-01 00:00:00 UTC-аас хойш өнгөрсөн секунд
echo time();              // 1718000000 (жишээ)

// Огноо форматлах
echo date('Y-m-d');       // 2024-06-15
echo date('d/m/Y');       // 15/06/2024
echo date('H:i:s');       // 14:30:45
echo date('Y-m-d H:i:s'); // 2024-06-15 14:30:45
echo date('l, d F Y');    // Saturday, 15 June 2024

// Монгол хэлд тохируулсан хэлбэр
$гарагууд = ['Ням', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'];
$сарууд   = ['', '1-р сар', '2-р сар', '3-р сар', '4-р сар',
              '5-р сар', '6-р сар', '7-р сар', '8-р сар',
              '9-р сар', '10-р сар', '11-р сар', '12-р сар'];

$гараг = $гарагууд[(int) date('w')];
$сар   = $сарууд[(int) date('n')];
echo date('Y') . " оны $сар " . date('j') . ", $гараг";
// 2024 оны 6-р сар 15, Бя
?>

date() форматын тэмдэгтүүд

php
<?php
date_default_timezone_set('Asia/Ulaanbaatar');

$одоо = time();

// Жил
echo date('Y', $одоо);    // 2024 — 4 оронтой жил
echo date('y', $одоо);    // 24   — 2 оронтой жил

// Сар
echo date('m', $одоо);    // 06   — тэгтэй (01–12)
echo date('n', $одоо);    // 6    — тэггүй (1–12)
echo date('M', $одоо);    // Jun  — товчилсон нэр
echo date('F', $одоо);    // June — бүтэн нэр
echo date('t', $одоо);    // 30   — тухайн сарын өдрийн тоо

// Өдөр
echo date('d', $одоо);    // 15   — тэгтэй (01–31)
echo date('j', $одоо);    // 15   — тэггүй (1–31)
echo date('D', $одоо);    // Sat  — товчилсон гараг
echo date('l', $одоо);    // Saturday — бүтэн гараг
echo date('N', $одоо);    // 6    — ISO гараг (1=Да, 7=Ня)
echo date('z', $одоо);    // 166  — жилийн өдөр (0–365)

// Цаг
echo date('H', $одоо);    // 14   — 24 цагийн (00–23)
echo date('h', $одоо);    // 02   — 12 цагийн (01–12)
echo date('i', $одоо);    // 30   — минут (00–59)
echo date('s', $одоо);    // 45   — секунд (00–59)

// Бусад
echo date('U', $одоо);    // Unix timestamp
echo date('W', $одоо);    // 24   — жилийн долоо хоног
echo date('L', $одоо);    // 1    — 2024 leap year мөн (1=тийм)
?>

strtotime() — мөрөөс timestamp үүсгэх

php
<?php
date_default_timezone_set('Asia/Ulaanbaatar');

// Огноо мөрийг timestamp болгоно
$timestamp = strtotime('2024-06-15');
echo date('Y-m-d', $timestamp);      // 2024-06-15

// Хүний хэлний илэрхийлэл
echo date('Y-m-d', strtotime('tomorrow'));         // маргааш
echo date('Y-m-d', strtotime('yesterday'));        // өчигдөр
echo date('Y-m-d', strtotime('next Monday'));      // дараагийн Даваа
echo date('Y-m-d', strtotime('last Friday'));      // өнгөрсөн Баасан
echo date('Y-m-d', strtotime('+7 days'));          // 7 хоногийн дараа
echo date('Y-m-d', strtotime('+1 month'));         // 1 сарын дараа
echo date('Y-m-d', strtotime('+1 year'));          // 1 жилийн дараа
echo date('Y-m-d', strtotime('-3 months'));        // 3 сарын өмнө

// Огноо тооцоолол
$захиалга_огноо = strtotime('2024-06-01');
$хүргэлт_огноо = strtotime('+14 days', $захиалга_огноо);
echo date('Y-m-d', $хүргэлт_огноо);   // 2024-06-15

// Хугацаа дуусаагүй эсэхийг шалгах
$дуусах_огноо = strtotime('2024-12-31');
if (time() <= $дуусах_огноо) {
    echo "Subscriрtion идэвхтэй.";
} else {
    echo "Subscription дууссан.";
}
?>

DateTime ба DateTimeImmutable класс

Объект хандлагатай, илүү найдвартай арга:

php
<?php
date_default_timezone_set('Asia/Ulaanbaatar');

// DateTime үүсгэх
$одоо   = new DateTime();
$хуучин = new DateTime('2024-01-01');
$тодорхой = new DateTime('2024-06-15 14:30:00');

echo $одоо->format('Y-m-d H:i:s');

// Огноо өөрчлөх
$одоо->modify('+1 month');
$одоо->modify('-7 days');
$одоо->modify('next Monday');
echo $одоо->format('Y-m-d');

// DateTimeImmutable — өөрчлөхөд шинэ объект буцаана (аюулгүй)
$огноо  = new DateTimeImmutable('2024-06-15');
$дараа  = $огноо->modify('+30 days');   // $огноо өөрчлөгдөхгүй
echo $огноо->format('Y-m-d');   // 2024-06-15 (хэвээр)
echo $дараа->format('Y-m-d');   // 2024-07-15

// Хоёр огноо хоорондын зөрүү
$эхлэл = new DateTime('2024-01-01');
$төгсгөл = new DateTime('2024-06-15');
$зөрүү = $эхлэл->diff($төгсгөл);

echo $зөрүү->days . " өдөр";      // 166 өдөр
echo $зөрүү->m    . " сар";       // 5 сар
echo $зөрүү->d    . " өдөр";      // 14 өдөр
echo $зөрүү->format('%y жил, %m сар, %d өдөр');
?>

Практик жишээ — захиалгын систем

php
<?php
date_default_timezone_set('Asia/Ulaanbaatar');

class ЗахиалгаЦаг
{
    // Хүргэлтийн огноо тооцоолох (ажлын өдрөөр)
    public static function хүргэлтийн_огноо(int $ажлын_өдөр): string
    {
        $одоо = new DateTimeImmutable();
        $тоолсон = 0;

        while ($тоолсон < $ажлын_өдөр) {
            $одоо = $одоо->modify('+1 day');
            $гараг = (int) $одоо->format('N');
            if ($гараг < 6) {   // 1–5 = Да–Ба
                $тоолсон++;
            }
        }

        return $одоо->format('Y-m-d');
    }

    // Огноо хүний уншихад тохирсон хэлбэрт оруулах
    public static function харуулах(string $огноо_мөр): string
    {
        $огноо = new DateTime($огноо_мөр);
        $өдрүүд = (new DateTime())->diff($огноо)->days;
        $өнгөрсөн = new DateTime() > $огноо;

        if ($өдрүүд === 0)      return 'Өнөөдөр';
        if ($өдрүүд === 1)      return $өнгөрсөн ? 'Өчигдөр' : 'Маргааш';
        if ($өдрүүд < 7)       return ($өнгөрсөн ? '-' : '+') . $өдрүүд . ' өдөр';
        return $огноо->format('Y-m-d');
    }
}

echo ЗахиалгаЦаг::хүргэлтийн_огноо(3);     // 3 ажлын өдрийн дараа
echo ЗахиалгаЦаг::харуулах('2024-06-14');   // Өчигдөр (жишээ)
echo ЗахиалгаЦаг::харуулах('2024-06-16');   // Маргааш
echo ЗахиалгаЦаг::харуулах('2024-07-01');   // +16 өдөр
?>

Дараагийн хичээлд:

PHPUnit тест бичихийг судална. Функц, класс зөв ажиллаж байгааг автоматаар шалгах unit тест хэрхэн бичих, assert методууд хэрхэн хэрэглэх, тестийг хэрхэн ажиллуулахыг үзнэ.