Tuto situaci jsem obsáhle řešil v PHP/MySQL aplikaci, kterou jsem napsal pro provozovatele soukromého tryskáče před více než rokem. Na těchto dvou platformách existují různé strategie pro zpracování časových pásem, ale vysvětlím, jak jsem to udělal. Nastavil jsem MySQL server na UTC a spustil každý PHP skript v časovém pásmu, které uživatel určí během procesu registrace pro uživatelský profil.
MySQL a PHP (PHP 5.2 a vyšší) mají nativní datové typy datetime. Datetime v MySQL je primitivní datový typ, zatímco PHP 5.2 a vyšší nabízí vestavěný Třída DateTime . Datový typ MySQL datetime nezahrnuje metadata pro časové pásmo, ale objekt PHP DateTime vždy obsahuje časové pásmo. Pokud konstruktor datatime PHP nespecifikuje volitelné časové pásmo ve druhém argumentu, pak konstruktor PHP datetime použije proměnnou prostředí php.
MySQL i PHP mají v konfiguračních souborech nastavené výchozí časové pásmo. MySQL používá datum a čas nastavený v konfiguračním souboru pro každé připojení db, pokud uživatel neurčí jiné časové pásmo po zahájení připojení příkazem SET time_zone = [timezone];
. PHP také nastavuje proměnnou prostředí timezone pro každý skript pomocí časového pásma nastaveného v konfiguračním souboru serveru a tuto proměnnou prostředí lze přepsat pomocí funkce PHP date_default_timezone_set()
po spuštění skriptu.
Třída PHP DateTime má vlastnost nazvanou timezone , což je PHP DateTimeZone objekt . Objekt DateTimeZone je určen pomocí řetězce pro přesné časové pásmo. seznam časových pásem je komplexní a má stovky jednotlivých časových pásem po celém světě. Časová pásma PHP budou automaticky zohledňovat letní čas.
Když uživatel ve webové aplikaci vygeneruje datum a čas, vytvořte objekt PHP datetime v časovém pásmu profilu uživatele. Poté použijte setTimezone
metoda pro úpravu objektu DateTime na časové pásmo UTC. Nyní máte datum a čas uživatele v UTC a můžete uložit hodnotu do databáze. Použijte format
DateTime
metoda k vyjádření dat jako řetězec ve formátu akceptovaném MySQL.
Uživatel tedy vygeneruje datum a čas a vy vytvoříte objekt PHP datetime v uživatelem zadaném časovém pásmu:
// set using an include file for user profile
$user_timezone = new DateTimeZone('America/New_York');
// 1st arg in format accepted by PHP strtotime
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone);
$date_object1->setTimezone(new DateTimeZone('UTC'));
$formated_string = $date_object1->format('Y-m-d H:i:s');
$query_string = "INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')";
Když načtete hodnotu z databáze, vytvořte v UTC a poté převeďte na časové pásmo uživatele.
$query_string = "SELECT `datetime1` FROM `t_table1`";
$date_object1 = new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'));
$date_object1->setTimezone($user_timezone);
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a');
Při použití této metody jsou vaše hodnoty data a času vždy uloženy v UTC uvnitř databáze a uživatel vždy zažije hodnoty v časovém pásmu svého profilu. PHP v případě potřeby opraví letní čas pro každé časové pásmo.
One gotcha:Toto vysvětlení nepokrývá datový typ časového razítka MySQL. K ukládání hodnot datetime doporučuji použít datový typ MySQL datetime, nikoli datový typ časové razítko. Datový typ časového razítka je popsán v příručce zde .
Upravit: Pole obsahující každý řetězec časového pásma PHP můžete vytvořit pomocí listIdentifiers , což je statická metoda třídy DateTimeZone.