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

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL: Reakce na: lukas

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.
avatar © 2005-2021 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.