Navigace

Hlavnφ menu

 

P°esn² v²chod a zßpad slunce v PHP

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.

Balhar, Jan (23. 7. 2003)