Dlaczego? Łatwiej bedzie mi to wyjasnic jesli wyjaśnijmy sobie jak dzialaja podstawowe funkcje czasu i daty.
podstawa jest tu oczywiscie time() - ktory zwraca nam tzw. znacznik (stamp) unixowy. Nie jest to zadna data, a raczej rodzaj kalendarza (dziala podobnie jak kalendarz astronomiczny, tyle ze mniej dokladnie), ktorego dana chwila jest zapisywana w postaci liczby calkowitej wyrazajacej ilosc sekund jakie minely od dnia 1 stycznia 1970 roku o godzinie 0.00 czasu GMT. I tu od razu nalezy unikac pokusy, ktorej ja sam swego czasu nie uniknalem, by dodawac roznice czasowa do tej funkcji. To najgorszy blad! Dowiedza sie o tym Ci, ktorzy zmienia serwer na serwer w innej strefie czasowej. Przy funkcji time() nie trzeba nic robic, poniewaz w kazdej strefie czasowej w jakiej moglby byc serwer zawsze zwroci te sama wartosc.
Problemem jest funkcja date(), ktora na podstawie znacznika zwraca nam date jaka byla(jest) w danej strefie. Musielibysmy uzyc funkcji gmdate(), ktora zwraca nam date zawsze ta sama, date strefy GMT. Wystraczyloby dodac tylko godzinke i byloby po robocie, ale... niestety strefa gmt nie pzrewiduje czasu letniego. Jesli jednak, co nie jest trudne, zrobimy to funkcja, to spotka nas zawod: jesli mamy serwer w stanach - czas letni tam jest wprowadzany tydzien pozniej niz u nas! To tez, choc trudniej, mozna spacyfikowac, ale dostaniemy juz funkcje potworka. Lepiej zrobic cos uniwersalnego. Dzieki czemy bedziemy mogli skakac latwo po strefach.
Zaczynamy:
tworzymy klase w osobnym pliku, ja go nazwalem jak klase udate.php
w nim ostwieramy klase i definiujemy zmienne:
<?php class udate { var $czl; var $czl_styl_klient; var $czl_styl_serwer; var $strefa; var $format; } ?>
:arrow: $czl przyjmuje wartości 0 lub 1. 0 - nie uwzgledniamy czasu letniego, 1 - uwzgledniamy
:arrow: $czl_styl_klient przyjmuje wartości "US" lub "UE". "US" - czas letni ma byc brany pod uwage jak w USA, gdzie zaczyna się w pierwsza niedziele kwietnia, "UE" - tak jak w krajach Unii, gdzie zaczyna sie w ostatnia niedziele marca. Czas letni w obu stylach konczy sie w tym samym dniu.
:arrow: $czl_styl_serwer przyjmuje wartości "US" lub "UE". musimy ustawic tak aby zgadzal sie z polozeniem serwera. jezeli serwer jest w kraju gdzie czas letni rozpoczyna sie w ostatnia niedziele marca wybieramy wartosc "UE", jesli w pierwsza niedziele kwietnia to "US".
:arrow: $strefa, wartosci w zakresie -12 do 12. okresla w jakiej strefie przebywamy, lub z jakiej strefy chcemy uzyskac czas. dla Polski jest to 1 a np,. dla Nowego Yorku -5
:arrow: $format, format daty. np: "Y-m-d".
Teraz ustawimy wartosci standardowe. To znaczy dla tych, dla ktorychi nie okreslimy wartosci przy wywolaniu klasy. Robimy tzw. konstruktora czyli funkcje o takiej samej nazwie jak klasa. Dzieki temu bedzie ona sie wywolywac automatycznie:
<?php function udate() { $this->czl=1; $this->czl_styl_klient=\"UE\"; $this->czl_styl_serwer=\"UE\"; $this->strefa=1; $this->format=\"Y-m-d H:i\"; } ?>
tu chyba wszytko jasne. Teraz musimy stworzyc funkcje, ktorymi bedziemy zmieniac nasze wartosci:
<?php function ustaw_czl($set) { if ($set==1 || $set==0) { $this->czl=$set; } else { $this->czl=$this->czl; } } function ustaw_czl_styl_klient($set) { if ($set==\"US\" || $set==\"UE\") { $this->czl_styl_klient=$set; } else { $this->czl_styl_klient=$this->czl_styl_klient; } } function ustaw_czl_styl_serwer($set) { if ($set==\"US\" || $set==\"UE\") { $this->czl_styl_serwer=$set; } else { $this->czl_styl_serwer=$this->czl_styl_serwer; } } function ustaw_strefa($set) { if ($set<12 || $set>-12) { $this->strefa=$set; } else { $this->strefa=$this->strefa; } } function ustaw_format($set) { $this->format=$set; } ?>
Oprocz zmiennej $format, kazda inna ma ma zabezpiedczenie - jesli podamy mu wartosc spoza dopuszczalnego zakresu zwroci nam wartosci zdefinowane na poczatku.
Teraz przechodzimy do sedna. Glowna funkcja:
<?php function pokaz_date($stamp) { /// if ($this->czl_styl_klient==\"UE\") { $day=25; while ($dow!=\"Sun\") { $day++; } $border=$a; } elseif($this->czl_styl_klient==\"US\") { $day=1; while ($dow!=\"Sun\") { $day++; } $border=$a; } /// if ($this->czl==1) { if (($this->czl_styl_klient==\"US\" && $this->czl_styl_serwer==\"US\")||($this->czl_styl_klient==\"UE\" && $this->czl_styl_serwer==\"UE\")) { } else { } } elseif($this->czl_styl_klient==\"US\" && $this->czl_styl_serwer==\"UE\") { if ($chk_dls==1 && $stamp>=$border) { } else { } } elseif($this->czl_styl_klient==\"UE\" && $this->czl_styl_serwer==\"US\") { if ($chk_dls==1 || ($stamp>=$border && $stamp<$border+(7*24*3600))) { } else { } } } elseif($this->czl==0) { } } ?>
Wyjasnie po krotce co sie tu dzieje:
:arrow: linia 2: paramtr $stamp to oczywiscie znacznik unixowy., ktory w danym momencie zostal zwrocony przez funkcje time()
:arrow: linia 4: tu sprawdzamy czy na serwerze jest juz czas letni.
:arrow: linia 8-29: musimy wiedziec kiedy dokladnie przechodzimy w danym roku na czas letni w US lub UE. Chodzi o to, zebysmy odpowiednio zkorektowali to co dostalismy w lini 4.
:arrow: od lini 32: tworzymy date za pomoca funkcji gmdate(), dodajac/odejmujac do/od znacznika odpowiednia liczbe sekund. wynika to ze zmiennej "strefa". W przypadku kiedy musimy wziac pod uwage czas letni, mamy trzy warunki: serwer i klient znajduja sie w takiej strefie gdzie czas letni zaczyna sie w tym samym dniu, serwer znajduje sie w strefie gdzie rozpoczecie czasu letniego jest w roznych dniach (2 przypadki).
Teraz kilka przykladow. Bierzemy na tapete stamp z chwili przejscia na czas letni: 985482000 to 2001-03-25 02:00 wg czasu CET (np. Polska) a 2001-03-25 03:00 uwzgledniajac przejscie na czas letni. Byla to chwila kiedy z gdziny 2.00 przesunelismy zegarki na godzine 3.00
jesli mamy serwer w Polsce:
<?php include \"udate.php\"; $udate=new udate(); $udate->pokaz_date(\"985482000\"); ?>
zwroci nam: "2001-03-25 03:00"
jesli w stanach:
<?php include \"udate.php\"; $udate=new udate(); $udate->ustaw_czl(1); $udate->ustaw_czl_styl_klient(\"UE\"); $udate->ustaw_czl_styl_serwer(\"US\"); $udate->ustaw_strefa(1); $udate->pokaz_date(\"985482000\"); ?>
zwroci nam znowu "2001-03-25 03:00", uzylem wszytkich dostepnych medod w celach pokazowych, niektorych nie trzeba bylo, bo i tak zawieraja wartosci juz zadeklarowane w konstruktorze
a jaka jest godzina w NY?:
<?php include \"udate.php\"; $udate=new udate(); $udate->ustaw_czl(1); $udate->ustaw_czl_styl_klient(\"US\"); $udate->ustaw_czl_styl_serwer(\"UE\"); $udate->ustaw_strefa(-5); $udate->pokaz_date(\"985482000\"); ?>
otrzymamy date: "2001-03-24 20:00"
=====
oto jednolita klasa:
<?php class udate{ var $czl; var $czl_styl_klient; var $czl_styl_serwer; var $strefa; var $format; function udate() { $this->czl=1; $this->czl_styl_klient=\"UE\"; $this->czl_styl_serwer=\"UE\"; $this->strefa=1; $this->format=\"Y-m-d H:i\"; } function ustaw_czl($set) { if ($set==1 || $set==0) { $this->czl=$set; } else { $this->czl=$this->czl; } } function ustaw_czl_styl_klient($set) { if ($set==\"US\" || $set==\"UE\") { $this->czl_styl_klient=$set; } else { $this->czl_styl_klient=$this->czl_styl_klient; } } function ustaw_czl_styl_serwer($set) { if ($set==\"US\" || $set==\"UE\") { $this->czl_styl_serwer=$set; } else { $this->czl_styl_serwer=$this->czl_styl_serwer; } } function ustaw_strefa($set) { if ($set<12 || $set>-12) { $this->strefa=$set; } else { $this->strefa=$this->strefa; } } function ustaw_format($set) { $this->format=$set; } function pokaz_date($stamp) { /// if ($this->czl_styl_klient==\"UE\") { $day=25; while ($dow!=\"Sun\") { $day++; } $border=$a; } elseif($this->czl_styl_klient==\"US\") { $day=1; while ($dow!=\"Sun\") { $day++; } $border=$a; } /// if ($this->czl==1) { if (($this->czl_styl_klient==\"US\" && $this->czl_styl_serwer==\"US\")||($this->czl_styl_klient==\"UE\" && $this->czl_styl_serwer==\"UE\")) { } else { } } elseif($this->czl_styl_klient==\"US\" && $this->czl_styl_serwer==\"UE\") { if ($chk_dls==1 && $stamp>=$border) { } else { } } elseif($this->czl_styl_klient==\"UE\" && $this->czl_styl_serwer==\"US\") { if ($chk_dls==1 || ($stamp>=$border && $stamp<$border+(7*24*3600))) { } else { } } } elseif($this->czl==0) { } } } ?>
jesli chcemy zwracac date do zmiennej to musimy zamienic w lini 140
:arrow: print $dat; na return $dat;
wtedy:
<?php include \"udate.php\"; $udate=new udate(); ?>
otrzymamy datę bieżącą.
aby powrocic do standardowych ustawien (przyjetych w kontruktorze), jeśli je zmienialismy, wystaczy wpisac:
<?php $udate->udate(); ?>
przyklad:
<?php include \"udate.php\"; $udate=new udate(); $udate->ustaw_czl_styl_klient(\"US\"); $udate->ustaw_format(\"H:i\"); $a=$udate->pokaz_date(\"985482000\"); $udate->udate(); $b=$udate->pokaz_date(\"985482000\"); ?>
zwroci nam:
02:00
2001-03-25 03:00