Zobrazení serverového času

Školení, která pořádám

Nemám rád, když se na stránkách samoúčelně zobrazují prvky, které s obsahem nemají nic společného. Dobrou ukázkou jsou JavaScriptové hodiny ukazující čas na počítači uživatele.

Docela něco jiného ale je, když se na stránkách zobrazují hodiny ukazující čas na straně serveru. To se může hodit třeba u obchodu s působností ve více časových pásmech a dostupností telefonické podpory jen v určitém čase. Nebo na stránkách banky jako rozhodný údaj pro provádění některých pokynů (např. expresních plateb možných jen v určitém časovém rozpětí).

Pro získání serverového času můžeme použít např. funkci date, pro jeho aktualizaci budeme potřebovat JavaScript:

<div id="local-time"><?php echo date("H:i:s"); ?></div>
<script type="text/javascript">
var time_offset = 1000 * <?php echo time(); ?> - (new Date()).getTime();
window.setInterval(function () {
	var local_time = new Date();
	local_time.setTime(local_time.getTime() + time_offset);
	var min = local_time.getMinutes();
	var sec = local_time.getSeconds();
	document.getElementById('local-time').innerHTML = local_time.getHours() + ':' + (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec;
}, 1000);
</script>

Na první pohled mnohem jednodušší řešení by bylo si na začátku do proměnné uložit serverový čas a v sekundových intervalech k němu přičítat jednu sekundu. Toto řešení by však narazilo v momentě, kdy by uživatel počítač uspal – po probuzení by se na stránce zobrazoval starý čas. To je důvod, proč se při každém zavolání funkce poměrně nákladně zjišťuje aktuální čas.

Pokud si skript spustíte na svém počítači, tak si nejspíš všimnete toho, že je čas o chvilku zpožděný. Důvod je ten, že se nepočítá se zlomky sekund. Obvykle to nevadí, ale pokud by to někomu přece jen vadilo, zde je řešení:

<div id="local-time"><?php echo date("H:i:s"); ?></div>
<script type="text/javascript">
var time_server = 1000 * <?php echo microtime(true); ?>;
var time_offset = time_server - (new Date()).getTime();
function time_set() {
	var local_time = new Date();
	local_time.setTime(local_time.getTime() + time_offset);
	var min = local_time.getMinutes();
	var sec = local_time.getSeconds();
	document.getElementById('local-time').innerHTML = local_time.getHours() + ':' + (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec;
}
window.setTimeout(function () { window.setInterval(time_set, 1000); time_set(); }, 1000 - time_server % 1000);
</script>

Kromě použití funkce microtime je důležité také to, že první aktualizace času se neprovede až za vteřinu, ale za její část na základě serverového času.

Jakub Vrána, Řešení problému, 14.3.2007, diskuse: 11 (nové: 0)

Diskuse

ikona Techi:

A zase tady máme vyznavače IE jako jediného prohlížeče

uzivatel:

Myslis innerHTML ?

V tomto musim povedat, ze to bol celkom pekny vynalez od MS. Ovela viac zjednodusuje pracu a navrh celeho JS ako keby si mal pouzit child nodes.

ikona Jakub Vrána OpenID:

Odkaz na dokumentaci vede na Mozilla.org, co je na tom IE only?

uzivatel:

Asi to nemala byt reakcia na mna :)

Ja innerHTML uplne v pohode beriem a pocitam s tym, ze s rozsirenim AJAXU sa tato direktiva rozsirila do vacsiny internetovych prehliadacov.
V Mozilla produktoch taketo nieco bolo dostupne myslim ze este v obdobi Netscape 7. Ak sa to zaviedlo az v dobe Mozilly 1.0 tak sa ospravedlnujem.

Dokonca vie byt rychlejsie ako DOM model

http://www.quirksmode.org/dom/innerhtml.html

Joelp:

innerHTML je naprosto v pořádku! To si pletete s MS innerTEXT ;-)

sup:

velmi uzitocna vec.

J:

Když vložím do kódu JavaScriptu následující kód php: <php echo microtime(true); ?>, skript je nefunkční.

vasava:

<?php echo microtime(true); ?>

Zuben45:

No mě to nějak nejde, stále se mi ukazuje čas u mě na pc když si ho změním :(

xerno:

Poznámka k druhémup říkladu: zde předpokládáte, že se první vteřina zobrazí až za určitý zlomek vteřiny, ale k tomu nikdy nemůže dojít ve vámi předpokládané přesnosti. Dejme tomu, že mám rychlý prohlížeč a spouštím si to na localhostu, ale pro běžné použití je to nesmyslné - někdo má mobilní internet, další má IE7 nebo starší (i když je jich už málo) a u nich ve zlomcích vteřiny raději nepředpokládat, protože úspěšné spuštění můžeme předpokládat až po úplném natažení funkce time_set() a když ještě předtím zobrazuji microtime, asi bych to měl co nejdříve flushnout ke klientovi, aby už s tím mohl pracovat, čimž se mi vytvoří další vlákno a informace microtime bude o to starší. Vždy tu bude docházet k nepřesnosti, která je v řádu mikrosekund fatální. V řádku sekund se to projeví jen minimálně a stejně to prohlížeč po pár minutách spozdí. Toto řešení nic kloudného neřeší, přesto pochvala, je to velice hezké zobrazení serverového času :-)

PP.SMuRF:

Díky moc!!

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.