3. díl - Dokončení knihovny DateUtils v PHP

PHP Knihovny Dokončení knihovny DateUtils v PHP American English version English version

V minulém dílu našeho seriálu tutoriálů o tvorbě knihoven pro PHP jsme rozpracovali jednoduchou utility třídu pro práci s datem a časem. Dnes ji dokončíme.

Hezké datum a čas

Nevím, jestli má tato podoba data a času nějaký název, ale já jsem si metody implementoval jako prettyDateTime() a prettyDate(). Pokud je datum dnes, včera nebo zítra, vypíše se selovy, tedy např. "Dnes". Pokud je někdy tento rok, vypíše se měsíc slovy, např. 2.ledna. Pokud je rok jiný než současný, vypíše se celé datum čísly, např. 2.1.2013. Případně se za hodnotu doplní ještě čas. Jistě uznáte, že toto je pro uživatele mnohem příjemnější, než hromada čísel. A s knihovnou to máte během okamžiku použité.

Nejprve si vytvořme privátní metodu, která nám převede nastavenou instanci DateTime na hezké datum:

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 metodě si uložíme současné datum a pokud se roky současného a zadaného data různí, vrátíme číselně zapsané datum i s rokem. Pokud jsou den a měsíc stejné, vrátíme "Dnes". Následně měníme současné datum a kontrolujeme, zda není včera nebo zítra. Jakmile vyčerpáme všechny možnosti, vrátíme den a měsíc slovy.

Konečně přidáme 2 veřejné metody, které nám datum naformátují do požadované 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še můžeme vyzkoušet převedením různých dat v různých formátech:

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ýsledek:

Hezká česká data v PHP

Opět vidíme, jak naše metoda naformátuje naprosto cokoli na lidsky příjemně čitelnou hodnotu.

Parsování

Přejděme k parsovací metodě. Na vstupu ji dáme české datum (např. 15.1.2014) a formát, v jakém má být datum/čas zapsané. Metoda buď vyhodí výjimku nebo vrátí datum v DB formátu.

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 metodě nejprve k řetězci s datem přidáme 00 sekund v případě, že je v něm 1 dvojtečka (uživatel zadává čas a nezadal vteřiny). Dále pomocí regulárních výrazů odstraníme bílé znaky před separátory, kterými jsou ":" a ".". Díky tomu projde např. i datum "15.1. 2014 12:00", které se přeloží na "15.1.2014 12:00:00". Výsledný formát data a času je tedy vždy bez mezer a se vteřinami.

Tento formát můžeme předat třídě DateTime, validaci data provede za nás. Na internetu pod validací data naleznete zoufalá řešení, která na datum volají explode() a podobně, která jsou vždy neúplná, zrovna kontrola rozsahů a zadání všech součástí data a času je poměrně náročná. Nikdy neprogramujte sami něco, co je součástí standardních knihoven jazyka! Nikdy to neuděláte tak kvalitně a to už jen proto, že PHP je v céčku. A i kdyby ano, je to vyhozený čas.

Instanci DateTime sdělíme formát a předáme ji naše datum. Ona se ho pokusí naparsovat. Jakékoli chyby nám vrátí v poli pomocí metody getLastErrors(). Pokud se zde nějaké objeví, vyhodíme výjimku s hláškou podle formátu, v opačném případě vrátíme datum v příslušném databázovém formátu. Výjimku můžete poté chytat někde při zpracovávání údajů a zobrazit ji uživateli. Za tímto účelem by bylo nejideálnější vytvořit si nějakou svou.

Funkci si hned můžeme vyzkoušet:

$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ýsledek:

Parsování českého data a času v PHP

Validace data

Pro úplnost si dodejme i metodu validDate(), která o daném datu zjistí, zda je validní:

public static function validDate($date, $format = self::DATETIME_FORMAT)
{
        try
        {
                self::parseDateTime($date, $format);
                return true;
        }
        catch (InvalidArgumentException $e)
        {
        }
        return false;
}

Metodu vyzkoušejme zadáním několika dat:

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ýsledek:

Validace českého datumu v PHP

Vidíme, že prošla opravu jen validní data.

Now()

Jelikož MySQL neumí pří vkládání nového řádku u formátu DateTime dosadit aktuální datum/čas, používám často ještě následující metodu, která vrátí současné datum a čas v databázovém formátu:

public static function dbNow()
{
        $dateTime = new DateTime();
        return $dateTime->format(self::DB_DATETIME_FORMAT);
}

Můžete si o mě myslet, že jsem barbar, protože nepoužívám nativní funkci NOW(), ale tuto pihu na kráse mi několikanásobně vyváží výhody vložení řádku do databáze přímo z PHP pole, které mi mimochodem přijde přímo z formuláře, dotaz se sám generuje a ušetří to spoustu práce. Pokud jste pracovali s místním databázovým wrapperem nad PDO, tak víte o čem mluvím. Pokud ne, dostaneme se k tomu u motivace k formulářové knihovně.

Opět vyzkoušíme:

echo(DateUtils::dbNow());

Výsledek:

DbNow v PHP

Okomentovanou knihovnu máte v příloze ke stažení, ať vám dělá radost :) Budu se těšit příště, kdy začneme psát podobnou utilitu třídy pro textové řetězce.


 

Stáhnout

Staženo 360x (6.19 kB)
Aplikace je včetně zdrojových kódů v jazyce php

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (14 hlasů) :
55555


 


Miniatura
Všechny články v sekci
Knihovny pro PHP

 

 

Komentáře

Avatar
MArtin
Člen
Avatar
MArtin:

Chem sa opytat ako by sa dala tato utilitka upravit pre multyjazycny web?
Okrem zmeny jazyka stavovych sprav, treba aj rozne formaty casu.
Proceduralne som riesil chybove hlasky kodom a za kodmi bol slovnik pre kazdy jazyk a casove formaty boli tiez v nejakom poli...

 
Odpovědět 29.10.2015 16:20
Avatar
Jiří Fabšic:

Tak nevím jak to děláš!!! Na webu se nenajdou lepší tutoriály, knihovny, výklad. Díky moc za knihovnu !

 
Odpovědět 14. září 21:56
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.