3. diel - Dokončenie knižnice DateUtils v PHP
V minulej lekcii, Knižnica DateUtils pre český dátum a čas v PHP , sme rozpracovali jednoduchú utility triedu pre prácu s dátumom a časom. Dnes ju dokončíme.
Pekné dátum a čas
Neviem, či má táto podoba dátumu a času nejaký názov, ale ja som si metódy implementoval ako prettyDateTime () a prettyDate (). Ak je dátum dnes, včera alebo zajtra, vypíše sa slovami, teda napr. "Dnes". Ak je niekedy tento rok, vypíše sa mesiac slovami, napr. 2.ledna. Ak je rok iný ako súčasný, vypíše sa celé dátum číslami, napr. 2.1.2013. Prípadne sa za hodnotu doplní ešte čas. Iste uznáte, že toto je pre užívateľov oveľa príjemnejšie, než hromada čísel. A s knižnicou to máte behom okamihu použité.
Najprv si vytvorme privátne metódu, ktorá nám prevedie nastavenú inštanciu DateTime na pekné dátum:
private static function getPrettyDate($dateTime) { $now = new DateTime(); if ($dateTime->format('Y') != $now->format('Y')) return $dateTime->format('j.n.Y'); $dayMonth = $dateTime->format('d-m'); if ($dayMonth == $now->format('d-m')) return "Dnes"; $now->modify('-1 DAY'); if ($dayMonth == $now->format('d-m')) return "Včera"; $now->modify('+2 DAYS'); if ($dayMonth == $now->format('d-m')) return "Zítra"; return $dateTime->format('j.') . self::$months[$dateTime->format('n') - 1]; }
V metóde si uložíme súčasnej dátum a ak sa roky súčasného a zadaného dátumu rôzni, vrátime číselne zapísanej dátum is rokom. Ak sú deň a mesiac rovnaké, vrátime "Dnes". Následne meníme súčasné dátum a kontrolujeme, či nie je včera alebo zajtra. Akonáhle vyčerpáme všetky možnosti, vrátime deň a mesiac slovami.
Konečne pridáme 2 verejné metódy, ktoré nám dátum naformátujú do požadovanej podoby:
public static function prettyDate($date) { return self::getPrettyDate(self::getDateTime($date)); } public static function prettyDateTime($date) { $dateTime = self::getDateTime($date); return self::getPrettyDate($dateTime) . $dateTime->format(' H:i:s'); }
Všetko môžeme vyskúšať prevedením rôznych dát v rôznych formátoch:
echo(DateUtils::prettyDate(1376906152) . '<br />'); echo(DateUtils::prettyDateTime('2014-02-23 10:50') . '<br />'); echo(DateUtils::prettyDateTime('2014-02-22 10:50') . '<br />'); echo(DateUtils::prettyDate('24.2.2014') . '<br />'); echo(DateUtils::prettyDate('2014-02-01') . '<br />'); echo(DateUtils::prettyDate('2013/02/20') . '<br />');
výsledok:
Opäť vidíme, ako naša metóda naformátuje úplne čokoľvek na ľudsky príjemne čitateľnú hodnotu.
Parsovanie
Prejdime k parsovací metóde. Na vstupe ju dáme českej dátum (napr. 15.1.2014) a formát, v akom má byť dátum / čas zapísané. Metóda buď vyhodí výnimku alebo vráti dátum v DB formáte.
public static function parseDateTime($date, $format = self::DATETIME_FORMAT) { if (mb_substr_count($date, ':') == 1) $date .= ':00'; // Smaže mezery před nebo za separátory $a = array('/([\.\:\/])\s+/', '/\s+([\.\:\/])/', '/\s{2,}/'); $b = array('\1', '\1', ' '); $date = trim(preg_replace($a, $b, $date)); // Smaže nuly před čísly $a = array('/^0(\d+)/', '/([\.\/])0(\d+)/'); $b = array('\1', '\1\2'); $date = preg_replace($a, $b, $date); // Vytvoří instanci DateTime, která zkontroluje zda zadané datum existuje $dateTime = DateTime::createFromFormat($format, $date); $errors = DateTime::getLastErrors(); // Vyvolání chyby if ($errors['warning_count'] + $errors['error_count'] > 0) { if (in_array($format, self::$errorMessages)) throw new InvalidArgumentException(self::$errorMessages[$format]); else throw new InvalidArgumentException('Neplatná hodnota'); } // Návrat data v MySQL formátu return $dateTime->format(self::$formatDictionary[$format]); }
V metóde najprv k reťazcu s dátumom pridáme 00 sekúnd v prípade, že je v ňom 1 dvojbodka (používateľ zadáva čas a nezadal sekundy). Ďalej pomocou regulárnych výrazov odstránime biele znaky pred separátory, ktorými sú ":" a ".". Vďaka tomu prejde napr. Aj dátum "15.1. 2014 12:00", ktoré sa preloží na "15.1.2014 12:00:00". Výsledný formát dátumu a času je teda vždy bez medzier a so sekundami.
Tento formát môžeme odovzdať triede DateTime, validáciu dáta vykoná za nás. Na internete pod validáciou dáta nájdete zúfalá riešenia, ktoré na dátum volajú explode () a podobne, ktoré sú vždy neúplná, zrovna kontrola rozsahov a zadaní všetkých súčastí dátumu a času je pomerne náročná. Nikdy neprogramujte sami niečo, čo je súčasťou štandardných knižníc jazyka! Nikdy to neurobíte tak kvalitne a to už len preto, že PHP je v céčku. A aj keby áno, je to vyhodený čas.
Inštanciu DateTime oznámime formát a odovzdáme ju naše dátum. Ona sa ho pokúsi naparsovat. Akékoľvek chyby nám vráti v poli pomocou metódy getLastErrors (). Ak sa tu nejaké objavia, vyhodíme výnimku s hláškou podľa formátu, v opačnom prípade vrátime dátum v príslušnom databázovom formáte. Výnimku môžete potom chytať niekde pri spracúvaní údajov a zobraziť ju užívateľmi. Na tento účel by bolo ideálne vytvoriť si nejakú svoju.
Funkciu si hneď môžeme vyskúšať:
$date = DateUtils::parseDateTime('24.2. 2014', DateUtils::DATE_FORMAT); echo($date . '<br />'); $dateTime = DateUtils::parseDateTime('24.2. 2014 10:30', DateUtils::DATETIME_FORMAT); echo($dateTime . '<br />'); $time = DateUtils::parseDateTime('10:30', DateUtils::TIME_FORMAT); echo($time . '<br />');
výsledok:
Validácia dáta
Pre úplnosť si dodajme aj metódu validDate (), ktorá o danom dátume zistí, či je validný:
public static function validDate($date, $format = self::DATETIME_FORMAT) { try { self::parseDateTime($date, $format); return true; } catch (InvalidArgumentException $e) { } return false; }
Metódu vyskúšajme zadaním niekoľkých údajov:
var_dump(DateUtils::validDate('24.2. 2014', DateUtils::DATETIME_FORMAT)); var_dump(DateUtils::validDate('24.2 14', DateUtils::DATE_FORMAT)); var_dump(DateUtils::validDate('29.2. 2014', DateUtils::DATE_FORMAT)); var_dump(DateUtils::validDate('29. 2. 2012', DateUtils::DATE_FORMAT)); var_dump(DateUtils::validDate('14:56', DateUtils::TIME_FORMAT)); var_dump(DateUtils::validDate('14:62', DateUtils::TIME_FORMAT));
výsledok:
Vidíme, že prešla opravu len validný dáta.
Now ()
Keďže MySQL nevie prí vkladaní nového riadku pri formáte DateTime dosadiť aktuálny dátum / čas, používam často ešte nasledujúce metódu, ktorá vráti súčasné dátum a čas v databázovom formáte:
public static function dbNow() { $dateTime = new DateTime(); return $dateTime->format(self::DB_DATETIME_FORMAT); }
Môžete si o mňa myslieť, že som barbar, pretože nepoužívam natívne funkciu NOW (), ale túto pehu na kráse mi niekoľkonásobne vyváža výhody vloženie riadku do databázy priamo z PHP poľa, ktoré mi mimochodom príde priamo z formulára, otázka sa sám generuje a ušetrí to veľa práce. Ak ste pracovali s miestnym databázovým wrapper nad PDO, tak viete o čom hovorím. Ak nie, dostaneme sa k tomu u motivácia k formulárové knižnici.
Opäť vyskúšame:
echo(DateUtils::dbNow());
výsledok:
Okomentovanou knižnicu máte v prílohe k stiahnutiu, nech vám robí radosť Budem sa tešiť nabudúce, u lekcie Riešené úlohy k 1.-3. lekciu knižnice v PHP , kedy začneme písať podobnú utility triedu pre textové reťazce.
V nasledujúcom cvičení, Riešené úlohy k 1.-3. lekciu knižnice v PHP, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 756x (3.26 kB)
Aplikácia je vrátane zdrojových kódov v jazyku php