Lekce 2 - Knihovna DateUtils pro český datum a čas v PHP
V minulé lekci, Úvod do knihoven a frameworků v PHP, jsme si vysvětlili, že knihovny jsou v PHP nutností a že se poté sdružují do frameworků.
V dnešním dílu si vytvoříme svou první knihovnu v PHP, půjde o
knihovnu DateUtils
. Před tvorbou každé knihovny si krátce
uvedeme, proč ji vlastně vytváříme.
Motivace
V PHP získáváme datum z databáze často ve formátu
yyyy-mm-dd
. Uživateli bychom ho samozřejmě chtěli vypsat v
českém tvaru a pomocí PHP funkcí si musíme pamatovat formáty jako
j.n.Y G:i:s
, které musíme stále dokola hledat v manuálu.
Ačkoli by datum teoreticky šlo formátovat přímo v databázi, tak do ní
prezentační logika nepatří a byl by problém, kdybychom tuto hodnotu třeba
později chtěli použít jako další vstup pro nějakou funkci. A úplně
ideálně bychom našemu uživateli datum chtěli vypsat jako
Dnes 15:15
nebo 15.ledna
.
Pokud ve formulářích nepoužíváme nějaký DatePicker
s
pomocí knihovny jQuery, přijde nám od
uživatele opět česky zapsané datum a my bychom ho potřebovali naparsovat na
databázový formát. Potřebujeme samozřejmě také ověřit, zda uživatel
zadal smysluplnou hodnotu a to nejen jestli zadal správně čísla a mezi nimi
tečky, ale i jestli nezadal např. 29.února
v nepřestupný
rok.
DateUtils
Za účelem těchto jednoduchých funkcí si vytvoříme třídu
DateUtils
. Bude se jednat o pomocnou (Utility
)
třídu, která nemá žádný vnitřní stav. Budeme ji také často používat
na mnoha místech aplikace. Z těchto charakteristik usoudíme, že její metody
bude nejlepší udělat statické.
Pokud používáte jmenné prostory, můžete si ji vložit do namespace
Utilities
, v dalších dílech budeme tvořit podobné třídy pro
práci s textovými řetězci a poli:
class DateUtils
{
}
Příprava konstant
Do třídy si dodejme několik konstant, kam si uložíme formáty, které
budeme při převodu používat. První 3 jsou české datum s časem, české
datum a český čas. Určitě nemusím připomínat, že např.
H:i:s
jsou hodiny:minuty:sekundy
,
jistě si dokážete z PHP manuálu zjistit, co který symbol znamená.
const DATETIME_FORMAT = 'j.n.Y G:i:s'; const DATE_FORMAT = 'j.n.Y'; const TIME_FORMAT = 'G:i:s'; const DB_DATETIME_FORMAT = 'Y-m-d H:i:s'; const DB_DATE_FORMAT = 'Y-m-d'; const DB_TIME_FORMAT = 'H:i:s';
Kód si řádně okomentujte pomocí PhpDoc.
Pomocná pole
Dále si vytvoříme 3 pomocná pole, musí být samozřejmě statická, abychom k nim měli přístup ze statických metod:
private static array $months = array('ledna', 'února', 'března', 'dubna', 'května', 'června', 'července', 'srpna', 'září', 'října', 'listopadu', 'prosince'); private static array $errorMessages = array( self::DATE_FORMAT => 'Neplatné datum, zadejte ho prosím ve tvaru dd.mm.rrrr', self::TIME_FORMAT => 'Neplatný čas, zadejte ho prosím ve tvaru hh:mm, můžete dodat i vteřiny', self::DATETIME_FORMAT => 'Neplatné datum nebo čas, zadejte prosím hodnotu ve tvaru dd.mm.rrrr hh:mm, případně vteřiny', ); private static array $formatDictionary = array( self::DATE_FORMAT => self::DB_DATE_FORMAT, self::DATETIME_FORMAT => self::DB_DATETIME_FORMAT, self::TIME_FORMAT => self::DB_TIME_FORMAT, );
Do prvního pole si vložíme české názvy měsíců, do druhého chybové hlášky pro jednotlivé formáty. Do třetího potom jak se mají formáty mezi sebou převádět, aby byl výsledek vždy v databázovém tvaru. Přijde mi vhodné v aplikaci pracovat s datem a časem právě v tomto formátu, databáze je alfa a omega celé aplikace, PHP je vlastně jen podpůrný jazyk.
Formátování data a času
Veškerá práce s datem a časem bude probíhat pomocí PHP třídy
DateTime
, která je geniálně navržená a určitě byste ji měli
znát.
Za účelem vytvoření instance DateTime
si vytvoříme
následující pomocnou metodu getDateTime()
:
public static function getDateTime(string $date): DateTime { if (ctype_digit($date)) $date = '@' . $date; return new DateTime($date); }
Metoda slouží k tomu, aby byla naše třída univerzální a dokázala
případně formátovat i datum z databáze v případě, že je zde
reprezentované jako datový typ int
(to je počet sekund od
UNIXové epochy). Zda je datum zadáno jako jedno číslo zjistíme funkcí
ctype_digit()
(zda je text obsahující pouze číslice). Ve
starších verzích PHP, kde nemůžeme určit datové typy v metodách, bychom
použili navíc ještě funkci is_int()
(zda je přímo již
číslo):
public static function getDateTime($date) { if (ctype_digit($date) || is_int($date)) $date = '@' . $date; return new DateTime($date); }
My ale víme, že máme k dispozici pouze datový typ string
,
čili číslo tam nikdy nebude, proto můžeme funkci is_int()
vynechat.
V případě platnosti podmínky přidáme před řetězec zavináč
@
. Třída DateTime
zavináč používá právě k
označení UNIX timestampu a už bude vědět, jak ho naparsovat. Nutno dodat,
že tento formát data je poněkud nešikovný a ve svých aplikacích se mu
spíše vyhněte, nicméně snažme se být univerzální.
Český formát
Pro formátování data s časem a samotného data z libovolné podoby do
podoby české (15.1.2014
) si vytvoříme dvě jednoduché
metody:
public static function formatDate(string $date): string { $dateTime = self::getDateTime($date); return $dateTime->format('d.m.Y'); } public static function formatDateTime(string $date): string { $dateTime = self::getDateTime($date); return $dateTime->format('d.m.Y H:i:s'); }
Metody můžeme používat v pohledech při výpisu data z výsledku
databázového dotazu. Za tímto účelem si v budoucnu vytvoříme třídu
FormatHelper
, která bude knihovnu DateUtils
využívat.
Jako vždy si logiku vyzkoušejme:
require_once('Utility/DateUtils.php'); echo(DateUtils::formatDate(1376906152) . '<br />'); echo(DateUtils::formatDateTime('2014-02-23 10:50') . '<br />'); echo(DateUtils::formatDate('24.2.2014') . '<br />'); echo(DateUtils::formatDate('2014-02-01') . '<br />'); echo(DateUtils::formatDate('2013/02/20') . '<br />');
Výsledek není zatím nijak světoborný, nicméně jednoduše převedeme jakkoli zadané datum do české podoby:
V příští lekci, Dokončení knihovny DateUtils v PHP, si naprogramujeme formátování na "hezký formát", jako např. "Dnes" nebo "15.ledna". Třídu dokončíme metodou, která validuje a parsuje česky zapsané datum.