[PHP] Jak wyliczyć kiedy nastąpi wschód i zachód Słońca dla dowolnego dnia?

0x01 graphic

Chcesz obliczyć godziny wschodu i zachodu Słońca w dowolnym dniu, np. dzisiaj w Warszawie:

dzień: 13.05.2004
wschód Słońca: 04:44
zachód Słońca: 20:21

0x01 graphic

Gdy podajesz na swojej stronie dzisiejszą datę, możesz proste kalendarium wzbogacić o informację na temat wschodów i zachodów Słońca. Aby obliczyć godzinę wschodu oraz zachodu, musisz określić szerokość i długość geograficzną miejsca, dla którego będą liczone godziny, a także określić dzień, dla którego chcesz otrzymać wynik.

Algorytm obliczający czas wschodu i zachodu jest dosyć skomplikowany, oto on:

<?

$dzien="26";

$miesiac="04";

$rok="2004";

$szerokosc = 52.00; // szerokość geograficzna Warszawy

$dlugosc = 21.00; // długość geograficzna Warszawy

// wschód

$tw = floor(275*$miesiac/9)-(floor(($miesiac+9)/12)*

(1+floor(($rok-4*floor($rok/4)+2)/3)))+$dzien-30+(6-$dlugosc/15)/24;

$mw = (0.9856*$tw)-3.289;

$lw = $mw+1.916*sin($mw*M_PI/180)+0.020*sin(2*$mw*M_PI/180)+282.634;

if ($lw>360) $lw -= 360; if ($lw<0) $lw += 360;

$raw = atan(0.91764*tan($lw*M_PI/180))*180/M_PI;

if ($raw>360) $raw -= 360; if ($raw<0) $raw += 360;

$raw = ($raw+(floor($lw/90)*90-floor($raw/90)*90))/15;

$sinDecw = 0.39782*sin($lw*M_PI/180);

$cosDecw = cos(asin($sinDecw));

$cosHw = (cos(90.5)*M_PI/180-($sinDecw*sin($szerokosc*M_PI/180)))/

($cosDecw*cos($szerokosc*M_PI/180));

$UTw = (360-acos($cosHw)*180/M_PI)/15+$raw-0.06571*$tw-6.622-$dlugosc/15;

if ($UTw>24) $UTw -= 24; if ($UTw<0) $UTw += 24;

$cw = sprintf("%02d", (gmmktime()-mktime())/60/60+floor($UTw)).":";

$cw .= sprintf("%02d", floor((($UTw-floor($UTw))*60)));

// zachód

$tz = floor(275*$miesiac/9)-(floor(($miesiac+9)/12)*

(1+floor(($rok-4*floor($rok/4)+2)/3)))+$dzien-30+(18-$dlugosc/15)/24;

$mz = 0.9856*$tz-3.289;

$lz = $mz+1.916*sin($mz*M_PI/180)+0.020*sin(2*$mz*M_PI/180)+282.634;

if ($lz>360) $lz -= 360; if ($lz<0) $lz += 360;

$raz = atan(0.91764*tan($lz*M_PI/180))*180/M_PI;

if ($raz>360) $raz -= 360; if ($raz<0) $raz += 360;

$raz = ($raz+(floor($lz/90)*90-floor($raz/90)* 90))/15;

$sinDecz = 0.39782*sin($lz*M_PI/180);

$cosDecz = cos(asin($sinDecz));

$cosHz = (cos(90.5)*M_PI/180-($sinDecz*sin($szerokosc*M_PI/180)))/

($cosDecz*cos($szerokosc*M_PI/180));

$UTz = (acos($cosHz)*180/M_PI)/15+$raz-0.06571*$tz-6.622-$dlugosc/15;

if ($UTz>24) $UTz -= 24; if ($UTz<0) $UTz += 24;

$cz = sprintf("%02d", (gmmktime()-mktime())/60/60+floor($UTz)).":";

$cz .= sprintf("%02d", floor((($UTz-floor($UTz))*60)));

// wynik:

echo "<p><b>dzień:</b> $dzien.$miesiac.$rok";

echo "<br><b>wschód Słońca:</b> $cw";

echo "<br><b>zachód Słońca:</b> $cz";

?>

Algorytm pochodzi z książki Almanac for Computers, wydanej przez Nautical Almanac Office United States Naval Observatory. Przekształciłem go w wersję PHP dodając lub modyfikując nieco poszczególne kroki obliczeń.

Założyłem, iż odległość zenitalna dla słońca jest standardowa i wynosi 90.5 stopnia. Można jeszcze zastosować 96 stopni dla zenitu cywilnego, 102 stopnie dla zenitu żeglarskiego i 108 stopni dla astronomicznego.

Ponieważ należy określić położenie punktu, dla którego obliczany jest wschód i zachód, użyłem przybliżonych wartości dla Warszawy. Dzień można również ustalić według własnych potrzeb, jeżeli ma to być dzień aktualny możesz użyć formuły:

$dzien=date("d");

$miesiac=date("m");

$rok=date("Y");

Dalej następuje szereg obliczeń, mających na celu ustalenie dnia roku, wyliczenia pozycji Słońca na horyzoncie i przeliczenie jej na czas uniwersalny, a następnie lokalny przez dodanie do czasu uniwersalnego godziny lub dwóch w zależności od czasu letniego lub zimowego.

Wszystkie zmienne zakończone na "w" dotyczą wschodu, a zmienne zakończone na "z" dotyczą zachodu.

Nie brałem pod uwagę sytuacji, gdy Słońce nie zachodzi lub nie wschodzi (np. w określonych porach na biegunach). Jeżeli $cosHw jest większe niż 1, wtedy Słońce w danym dniu nie wschodzi, a jeżeli $cosHz jest mniejsze niż -1, wtedy nie zachodzi.