Práce s datem
Školení, která pořádám
V PHP se pro uložení data používá podobně jako např. v jazyce C tzv. timestamp – počet vteřin uplynulých od 1.1.1970. Tento formát svádí k „posunům v čase“ pouhým přičítáním čísel:
<?php
$dnes = mktime(0, 0, 0, $_GET["mesic"], $_GET["den"], $_GET["rok"]);
$vcera = $dnes - 24*60*60; // nebo hůře: $dnes - 86400
?>
Problém s touto aritmetikou nastává ve dnech, kdy se mění letní čas na zimní nebo zpět – v takových případech můžeme dostat o den míň. Pro posuny v čase je proto lepší použít funkci mktime nebo rovnou strtotime:
<?php
$vcera = mktime(0, 0, 0, date("n", $dnes), date("j", $dnes) - 1, date("Y", $dnes));
$vcera = strtotime("-1 day", $dnes);
?>
Funkce mktime je inteligentní – i když se jí předají neplatné parametry, vrátí platné datum (např. 1.13.2004 převede na 1.1.2005), pro posuny v čase je nicméně trochu krkolomná.
Diskuse
JersyWoo:
Díky za info, tuhle funkci jsem neznal.
Al:
jj, strtotime jsem taky jseště neviděl. učil jsem se používat php (slovo programovat bych v mém případě nepoužil) z knihy od Koska a ten to tam nemá.
lukas:
treba hloupy dotaz, ale proc je rozdil v $dnes - 24*60*60; a $dnes - 86400;
?
dik
Čistě kvůli čitelnosti. Z 24*60*60 je na první pohled patrné, že to bude jeden den, z 86400 až na druhý ;-).
lukas:
respektive, nekdo mi zada dva dny, potrebuju rozdil
<?php
$d1 = "2005-04-02";
$d2 = "2005-04-05";
$arrive = strtotime($d1);
$odjezd = strtotime($d2);
$rozdil = $odjezd - $arrive;
$dnu = $rozdil / 86400;
?>
Je to nespolehlive kvuli prechodu letni/zimni cas?
V tomto případě stačí použít round(). Ne ceil() ani floor(), protože každý z nich by při jednom přechodu nefungoval.
<?php
$d1 = "2005-10-29";
$d2 = "2005-10-31";
echo $dnu; // 2.04166666667
?>
lukas:
ano pouzivam round(), jen jsem to tam nedopsal, ale o to neslo, spis jestli nemuze nastat nejaka nepresnost a zda je to 100%
ukazal jsem to jednomu javistovi a docela se smal ze je to prasarna, jenze me nenapada jak jinak v php toto provest, krome nejakeho pearu, jenze hostingy vetsinou ignoruji potrebu nejaky balik, nebo extension doplnit, ale vymlouvaji se na bezpecnost
diky za reakci
V tomto případě mě nenapadá, jak to udělat čistěji. Posun času je o hodinu a ne o půl dne, takže round() se s tím vyrovná.
Pro instalaci většiny balíků z PEARu administrátora nepotřebuješ.
kubakista:
Zdravím,
rád bych se zeptal, jak by se dala spolehlivě zohlednit změna času pokud by datum obsahoval i čas.
Mám na mysli rozdíl těchto dat ve dnech, tzn. tak aby výsledkem byly celé dny, v tomto případě 1 den.
<?php
$d1 = "2005-10-29 05:00:00";
$d2 = "2005-10-31 02:00:00";
?>
Díky.
PeSo:
Narazil jsem na nasledujici problem:
<?php
echo date("H:i:s",5);
?>
Vysledkem je 01:00:05 (cekal bych 00:00:05). Co je prosim spravne? (potrebuji prevadet vteriny na hod.,min. a sek., mozna by to slo delat uplne jinak).
diky za reakci
Jakub Vrána :
Můžeš použít gmdate() nebo <?php date("H:i:s", mktime(0, 0, 3661)); ?>
honza198:
zdravíčko, mám takový problém s datumem a časem:
potřebuji aktomaticky zjistit začátek a konec aktuálního měsíce (ikdyž je leden,únor, ... ) a převézt ho do Unix Stampu (vše s vteřinovou přesností) + potřebuju vše tak i zpět převádět.
Nesektal jste se stimhle problémem?
Jakub Vrána :
Timestamp:
<?php
mktime(0, 0, 0, date("n"), 1);
mktime(0, 0, 0, date("n") + 1, 1);
?>
Není mi jasné, co má znamenat "převod zpět", ale nejspíš ho zařídí funkce date().
Dtr:
Díky moc za stručné vysvětlení, přesně tuto funkci jsem potřeboval.
Kuba:
... není v tom druhém příkladu chyba? Nemá tam být v prvním řádku $dnes a pak ve druhém $vcera?
Ivo Toman:
Dobré vědět o: (je to ukázka knihy z PHP OOP Solutions)
<?php
// create a DateTime object
$date = new DateTime('Aug 31, 2008');
echo '<p>Initial date is ' . $date->format('F j, Y') . '</p>';
TAKING THE PAIN OUT OF WORKING WITH DATES
103
// add one month
$date->modify('+1 month');
echo '<p>Add one month: ' . $date->format('F j, Y') . '</p>';
// subtract one month
$date->modify('-1 month');
echo '<p>Subtract one month: ' . $date->format('F j, Y') . '</p>';
?>
protože může vést k neočekávaným výsledkům.
PedroKV:
chlapi, co dělám špatně, když
$mesic=date('n', strtotime('-1 month'));
$rok=date('Y', strtotime('-1 month'));
vrátí $mesic 5 a $rok 2011 a to i přes to, že aktuálně je 31.5.2011 22:00?
zároveň ale, ve stejný datum a čas, vrátí výraz
$mesic=date('n');
$rok=date('Y');
vrátí taktéž 5/2011.
Používám to na nasávání csv dat z Weather underground a zobrazování grafu a teď jsem zjistil, že mám 2x květen a jednou březen. Když jsem zjistil, že mám na stránce 2 květny a jeden březen, tak jsem si přidal pro odladění echo $rok,$mesic po předchozích kódech a zjistil to. Napadá mě, jestli strtotime nemá problém buď s 31 dny v květnu, ev. ještě s časovou zónou, že někde na serveru už se to může tvářit jako červen, ale zřejmě čistě jen pro strtotime, protože date je OK. Tak nevím, poraďte prosím.
PedroKV:
doplnění: jak jsem předpokládal, teď po půlnoci strtotime funguje správně. Tak kde je chyba? Zkusil jsem timezone setnout na Europe/Prague, ale nic.
Jakub Vrána :
Odečtením měsíce z 31.5. vznikne 31.4., což se převede na 1.5. Použil bych <?php mktime(12, 0, 0, date("n") - 1, 1) ?>.
PedroKV:
a můžeš mi to prosím napsat polopatě, jak do proměnné $mesic a $rok dostat touto funkcí minulý měsíc? Moc děkuji. Už jsem v PHP zase dlouho nedělal.
Colesnicov Denis Petrovic:
S PHP pracuji už více jak tři roky ale pořad se mám co učit. Velice poučne a užitecne :)
kajda:
Parádní, díky moc za info.. s blížící se změnou data už došlo na ony chyby kvůli "posunům v čase" a takhle se to zachránilo :)
Hrubý:
Dobrý den, mohl bych poprosit o pomoc. Potřeboval bych zjistit datum neděle v libovolně zvoleném týdnu a roku.
Příklad zadání rok 2013, týden 38. Výsledek 2013-09-22.
Moc děkuji.
Diskuse je zrušena z důvodu spamu.