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á.

Jakub Vrána, Výuka, 19.9.2005, diskuse: 25 (nové: 0)

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

ikona Jakub Vrána OpenID:

Č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?

ikona Jakub Vrána OpenID:

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

ikona Jakub Vrána OpenID:

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.

ikona Jakub Vrána OpenID:

Zkusil bych http://php.net/datetime.diff.

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

ikona Jakub Vrána OpenID:

Můžeš použít gmdate() nebo <?php date("H:i:s", mktime(0, 0, 3661)); ?>

Martin:

Pravdu má PHP. Funkce mkTime totiž převádí čas do odpovídající časové zóny. 1.1.1970 00:00:05 GMT znamená 1.1.1970 01:00:05 SEČ.

http://cz2.php.net/manual/en/datetime.settimezone.php

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?

ikona Jakub Vrána OpenID:

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?

ikona 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.

ikona Jakub Vrána OpenID:

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.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.