Přesný východ a západ slunce v PHP

23. července 2003

V následujícím článku vám předvedu, jak můžete pomocí PHP vypočítat přesný čas východu a západu slunce na daném místě v daném čase. Navíc také zjistíte, pod jakým azimutem slunce vychází a zapadá.

Původní skript jsem našel kdysi na jednom americkém serveru o astronomii, byl napsán v „nesmrtelném“ Basicu již před léty (cca rok 1993). Basic je celkem srozumitelný programovací jazyk a tak jsem bez větších obtíží přepsal skript do PHP. Upozorňuji, že jde o přesný astronomický výpočet, který počítá i s polárním dnem a nocí v severních a jižních oblastech naší planety. Pokud mu nebudete rozumět, nic si z toho nedělejte, pravděpodobně by i jeho autor měl problém se srozumitelným vysvětlením.

Nejdříve si vytvoříme stránku formular.php, na kterou umístíme formulář s potřebnými údaji k výpočtu. Po odeslání se dostaneme na stránku vypocet.php. Pro výpočet potřebujeme získat zemskou šířku a délku. Také chceme, aby bylo možné zadat datum, pro které se východ a západ slunce vypočítá. Poslední údaj, který potřebujeme, je časové pásmo dané pozice (výsledek poté můžeme uvést v místním čase a ne v GMT).

<FORM METHOD=“POST“ ACTION=“vypocet.php“>
<TABLE><TR><TD>
<fieldset style=“border: 1px solid #000000;“>
<legend>Výpočet západu a východu slunce kdekoliv a kdykoliv na zemi!</legend>
<TABLE width=400 border=0 cellspacing=0 cellpadding=5><TR><TD colspan=2 class=vlevo>
<INPUT maxlength=3 size=3 TYPE=“text“ value=““ NAME=“sirka“> stupňů,
<INPUT maxlength=2 size=1 TYPE=“text“ value=““ NAME=“minut1″> minut a
<INPUT maxlength=2 size=1 name=vterin1 TYPE=“text“ value=““> vteřin
<SELECT NAME=“sirka2″>
<OPTION VALUE=“severni“>severní</OPTION>
<OPTION VALUE=“jizni“>jižní</OPTION>
</SELECT> šířky.
</TD></TR><TR><TD colspan=2>
<INPUT maxlength=3 size=3 TYPE=“text“ value=““ NAME=“delka“> stupňů,
<INPUT maxlength=2 size=1 TYPE=“text“ value=““ NAME=“minut2″> minut a
<INPUT maxlength=2 size=1 name=vterin2 TYPE=“text“ value=““> vteřin
<SELECT NAME=“delka2″>
<OPTION VALUE=“vychodni“>východní</OPTION>
<OPTION VALUE=“zapadni“>západní</OPTION>
</SELECT> délky.
</TD></TR><TR><TD>
Rok:
</TD><TD><INPUT size=4 TYPE=“text“ NAME=“rok“ value=“<? echo date(Y); ?>“>
</TD></TR><TR><TD>
Měsíc:
</TD><TD width=260>
<SELECT NAME=“mesic“>
<OPTION VALUE=“1″ <? if (date(n) == 1) echo „selected“; ?>>leden</OPTION>
<OPTION VALUE=“2″ <? if (date(n) == 2) echo „selected“; ?>>únor</OPTION>
<OPTION VALUE=“3″ <? if (date(n) == 3) echo „selected“; ?>>březen</OPTION>
<OPTION VALUE=“4″ <? if (date(n) == 4) echo „selected“; ?>>duben</OPTION>
<OPTION VALUE=“5″ <? if (date(n) == 5) echo „selected“; ?>>květen</OPTION>
<OPTION VALUE=“6″ <? if (date(n) == 6) echo „selected“; ?>>červen</OPTION>
<OPTION VALUE=“7″ <? if (date(n) == 7) echo „selected“; ?>>červenec</OPTION>
<OPTION VALUE=“8″ <? if (date(n) == 8) echo „selected“; ?>>srpen</OPTION>
<OPTION VALUE=“9″ <? if (date(n) == 9) echo „selected“; ?>>září</OPTION>
<OPTION VALUE=“10″ <? if (date(n) == 10) echo „selected“; ?>>říjen</OPTION>
<OPTION VALUE=“11″ <? if (date(n) == 11) echo „selected“; ?>>listopad</OPTION>
<OPTION VALUE=“12″ <? if (date(n) == 12) echo „selected“; ?>>prosinec</OPTION>
</SELECT>
</TD></TR><TR><TD width=140>
Den:
</TD><TD>
<INPUT size=2 TYPE=“text“ NAME=“den“ value=“<? echo date(j); ?>“>
</TD></TR><TR><TD>Časové pásmo:
</TD><TD>
<SELECT NAME=“zona“>
<? for ($x=-12;$x<13;$x++): ?>
<OPTION <? if ($x==1) echo “ selected „;?> VALUE=“<? echo $x; ?>“>GMT <? if ($x > -1) echo „+“; echo $x; ?>:00</OPTION>
<? endfor;?>
</SELECT>
</TD></TR><TR><TD colspan=2>
<INPUT TYPE=“SUBMIT“ VALUE=“Výpočet“>
<INPUT TYPE=“RESET“ VALUE=“Původní hodnoty“>
</TD></TR></TABLE>

Předchozí kód vytváří formulář s pojmenovanými vstupními poli. Inputy s datumem jsou automaticky předvyplněny pro aktuální den. Odesílání údajů na stránku vypocet.php nepodléhá žádné kontrole, pokud byste tento skript nasazovali do „ostrého“ provozu, museli byste ho patřičně ošetřit.

<?php
if ($sirka2==’jizni‘): $sirka = -$sirka; endif;
if ($delka2==’zapadni‘): $delka = -$delka; endif;
echo „<h2>Výsledky výpočtu (není brán ohled na případný letní čas!)</h2>“;
echo „<BR><p><B>Kdy?</B> „.$den.“.“.$mesic.“.“.$rok. “ <br><B>Šířka?</B> „.(max($sirka,-$sirka)).“. stupeň, „.$minut1.“. minuta a „.$vterin1.“. vteřina „;
if ($sirka2==’severni‘): echo „severní“; else: echo „jižní“; endif;
echo “ šířky<BR><B>Délka?</B> „.(max($delka,-$delka)).“. stupeň, „.$minut2.“. minuta a „.$vterin2.“. vteřina „;
if ($delka2==’vychodni‘): echo „východní“; else: echo „západní“; endif;
echo “ délky<BR><B>Časové pásmo:</B> GMT „;
if ($zona>=0): echo ‚+‘; endif;
echo $zona.“:00<BR><BR>“;
function SGN($VALUE){
if ($VALUE == 0):
return 0;
elseif ($VALUE > 0):
return 1;
else:
return -1;
endif;
}
$P1 = 3.14159265;
$P2 = 2 * $P1;
$DR = $P1 / 180;
$K1 = 15 * $DR * 1.0027379;
$S_MESSAGE = „<B>Západ Slunce:</B> „;
$R_MESSAGE = „<B>Východ Slunce:</B> „;
$M1_MESSAGE = „Nedochází k východu Slunce.“;
$M2_MESSAGE = „Nedochází k západu Slunce.“;
$M3_MESSAGE = „Slunce nevychází (polární noc).“;
$M4_MESSAGE = „Slunce svítí celý den (polární den).“;
$minut1 = $minut1 + ((1/60)*$vterin1);
$minut2 = $minut2 + ((1/60)*$vterin2);
$sirka = $sirka + ((1/60)*$minut1);
$delka = $delka + ((1/60)*$minut2);
$B5 = $sirka;
$L5 = $delka;
$H = -$zona;
$L5 = $L5 / 360;
$Z0 = $H / 24;
$Y = $rok;
$M = $mesic;
$D = $den;
$G = 1;
IF ($Y < 1583) $G = 0;
$D1 = $D;
$F = $D – $D1 – 0.5;
$J = -intval(7 * (intval(($M + 9) / 12) + $Y) / 4);
if ($G <> 0):
$S = SGN($M-9);
$A = abs($M-9);
$J3 = intval($Y + $S * intval($A / 7));
$J3 = -intval((intval($J3 / 100) + 1) * 3 / 4);
endif;
$J = $J + intval(275 * $M / 9) + $D1 + $G * $J3;
$J = $J + 1721027 + 2 * $G + 367 * $Y;
if (F < 0):
$F = $F + 1;
$J = $J – 1;
endif;
$T = ($J – 2451545) + $F;
$TT = $T / 36525 + 1;
$T0 = $T / 36525;
$S = 24110.5 + 8640184.812999999 * $T0;
$S = $S + 86636.6 * $Z0 + 86400 * $L5;
$S = $S / 86400;
$S = $S – intval($S);
$T0 = $S * 360 * $DR;
$T = $T + $Z0;
$L = 0.779072 + 0.00273790931 * $T;
$G = 0.993126 + 0.0027377785 * $T;
$L = $L – intval($L);
$G = $G – intval($G);
$L = $L * $P2;
$G = $G * $P2;
$V = 0.39785 * sin($L);
$V = $V – 0.01 * sin($L – $G);
$V = $V + 0.00333 * sin($L + $G);
$V = $V – 0.00021 * $TT * sin($L);
$U = 1 – 0.03349 * cos($G);
$U = $U – 0.00014 * cos(2 * $L);
$U = $U + 0.00008 * cos($L);
$W = -0.0001 – 0.04129 * sin(2 * $L);
$W = $W + 0.03211 * sin($G);
$W = $W + 0.00104 * sin(2 * $L – $G);
$W = $W – 0.00035 * sin(2 * $L + $G);
$W = $W – 0.00008 * $TT * sin($G);
$S = $W / sqrt($U – $V * $V);
$A5 = $L + atan($S / sqrt(1 – $S * $S));
$S = $V / sqrt($U);
$D5 = atan($S / sqrt(1 – $S * $S));
$R5 = 1.00021 * sqrt($U);
$A_1 = $A5;
$D_1 = $D5;
$T = $T + 1;
$L = 0.779072 + 0.00273790931 * $T;
$G = 0.993126 + 0.0027377785 * $T;
$L = $L – intval($L);
$G = $G – intval($G);
$L = $L * $P2;
$G = $G * $P2;
$V = 0.39785 * sin($L);
$V = $V – 0.01 * sin($L – $G);
$V = $V + 0.00333 * sin($L + $G);
$V = $V – 0.00021 * $TT * sin($L);
$U = 1 – 0.03349 * cos($G);
$U = $U – 0.00014 * cos(2 * $L);
$U = $U + 0.00008 * cos($L);
$W = -0.0001 – 0.04129 * sin(2 * $L);
$W = $W + 0.03211 * sin($G);
$W = $W + 0.00104 * sin(2 * $L – $G);
$W = $W – 0.00035 * sin(2 * $L + $G);
$W = $W – 0.00008 * $TT * sin($G);
$S = $W / sqrt($U – $V * $V);
$A5 = $L + atan($S / sqrt(1 – $S * $S));
$S = $V / sqrt($U);
$D5 = atan($S / sqrt(1 – $S * $S));
$R5 = 1.00021 * sqrt($U);
$A_2 = $A5;
$D_2 = $D5;
if ($A_2 < $A_1):
$A_2 = $A_2 + $P2;
endif;
$Z1 = $DR * 90.833;
$S = sin($B5 * $DR);
$C = cos($B5 * $DR);
$Z = cos($Z1);
$M8 = 0;
$W8 = 0;
$A0 = $A_1;
$D0 = $D_1;
$DA = $A_2 – $A_1;
$DD = $D_2 – $D_1;
for ($C0 = 0; $C0 <= 23; $C0++):
$P = ($C0 + 1) / 24;
$A2 = $A_1 + $P * $DA;
$D2 = $D_1 + $P * $DD;
$L0 = $T0 + $C0 * $K1;
$L2 = $L0 + $K1;
$H0 = $L0 – $A0;
$H2 = $L2 – $A2;
$H1 = ($H2 + $H0) / 2;
$D1 = ($D2 + $D0) / 2;
if ($C0 <= 0):
$V0 = $S * sin($D0) + $C * cos($D0) * cos($H0) – $Z;
endif;
$V2 = $S * sin($D2) + $C * cos($D2) * cos($H2) – $Z;
if (SGN($V0) <> SGN($V2)):
$V1 = $S * sin($D1) + $C * cos($D1) * cos($H1) – $Z;
$A = 2 * $V2 – 4 * $V1 + 2 * $V0;
$B = 4 * $V1 – 3 * $V0 – $V2;
$D = $B * $B – 4 * $A * $V0;
if ($D >= 0):
$D = sqrt($D);
if (($V0 < 0) AND ($V2 > 0)): echo $R_MESSAGE; endif;
if (($V0 < 0) AND ($V2 > 0)): $M8 = 1; endif;
if (($V0 > 0) AND ($V2 < 0)): echo $S_MESSAGE; endif;
if (($V0 > 0) AND ($V2 < 0)): $W8 = 1; endif;
$E = (-$B + $D) / (2 * $A);
if (($E > 1) OR ($E < 0)): $E = (-$B – $D) / (2 * $A); endif;
$T3 = $C0 + $E + 1 / 120;
$H3 = intval($T3);
$M3 = intval(($T3 – $H3) * 60);
$VYPIS_M3 = $M3;
if (strlen($VYPIS_M3)==1) $VYPIS_M3 = „0“.$VYPIS_M3;
echo „“.$H3.“:“.$VYPIS_M3;
$H7 = $H0 + $E * ($H2 – $H0);
$N7 = -cos($D1) * sin($H7);
$D7 = $C * sin($D1) – $S * cos($D1) * cos($H7);
$AZ = atan($N7 / $D7) / $DR;
if ($D7 < 0): $AZ = $AZ + 180; endif;
if ($AZ < 0): $AZ = $AZ + 360; endif;
if ($AZ > 360): $AZ = $AZ – 360; endif;
echo “ (azimut = „.intval($AZ).“ stupňů)<BR>“;
endif;
endif;
$A0 = $A2;
$D0 = $D2;
$V0 = $V2;
endfor;
if (($M8 == 0) AND ($W8 == 0)):
if ($V2 < 0): echo $M3_MESSAGE; endif;
if ($V2 > 0): echo $M4_MESSAGE; endif;
else:
if ($M8 == 0): echo $M1_MESSAGE; endif;
if ($W8 == 0): echo $M2_MESSAGE; endif;
endif;
?>

Předchozí kód vypíše na stránku zadané údaje a výsledek výpočtu (čas východu a západu i s azimutem). Výsledky jsou uvedeny v čase pásma, které jste zadali. Nepočítají sice s letním časem, berou však ohled i na rotaci zemské osy a jiné vlivy, způsobující různé odchylky. Postup je optimalizován pro výpočty v příštích cca třiceti letech a je velmi přesný.

Pokud si chcete ověřit, zda skript funguje, zadejte souřadnice Prahy (pro zeměpisem netknuté připomínám 50° severní šířky a 15° východní délky) a porovnejte s předpovědí počasí na teletextu stanice ČT1 (v současné době je východ a západ slunce na straně 175), výsledek by se měl shodovat. Nevím přesně, pro jaké souřadnice provádí výpočet ČT, někdy se však údaje o minutu liší. Zkuste v takovém případě zadat přesnější souřadnice Prahy, které si snadno zjistíte v atlasu.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

3 komentářů

  1. Loder

    Říj 30, 2013 v 16:07

    u druheho kodu radite dopsat sirku a delku, ale tim ze nedelam v php nevim kam to presne doplnit navit mi to nesedi se strankou http://calendar.zoznam.sk/sunset-cz.php?city=3063548, ale to bude asi probelm letniho a zimniho casu, dekuji za odpoved

    Odpovědět
  2. martin

    Zář 11, 2015 v 15:30

    ja si rikam jestli ten formular nema bej spis jako html

    Odpovědět
  3. Vratislav Červenka

    Čvn 8, 2016 v 8:50

    Potřebuji časy východů a západů s přesností na sekundy. Uspokojí skript tento můj požadavek? O PHP jsem dodnes netušil, že něco takového vůbec existuje. Než se tím vším začnu prokousávat, prosím, můžete mi zodpovědět dotaz nahoře?

    Odpovědět

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *