Reklama

zonerbooks.cz | zoner.cz | czechia.com | regzone.cz | inshop.cz | inmail.cz | zonerpress.cz | zonerantivirus.com | zonerama.cz

interval.cz

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

23. 07. 2003 | Jan Balhar | PHP | Komentáře: 0

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.


Reklama


Další aktuální články na interval.cz

Tematicky související články

Dejte vědět i ostatním o článku

Diskuse (počet komentářů: 0)

Buďte prvním návštěvníkem, který přidá nový komentář.

Přidat nový komentář

Jméno a e-mail jsou nepovinné. Příspěvky obsahující odkaz jsou moderovány.

Zoner AntiVirus Free pro Android
zabezpečte si svůj smartphone, zdarma
Profesionální eshop Zoner inShop od 990 Kč.
Reklama
Reklama

Syndikace

hledáme nové autory | redakce interval.cz | reklama na interval.cz

© ZONER software, a.s., všechna práva vyhrazena, interval.cz dodržuje právní předpisy o ochraně osobních údajů. Powered by WordPress.