function _weather_calculate_sunrise_sunset in Weather 6.5
Same name and namespace in other branches
- 5.6 weather_parser.inc \_weather_calculate_sunrise_sunset()
- 7 weather_parser.inc \_weather_calculate_sunrise_sunset()
Calculate the times of sunrise and sunset
The times are GMT, so it's possible for the sunrise being at 16:48 while the sun sets at 7:06.
Parameters
array Parsed METAR data, will be altered:
1 call to _weather_calculate_sunrise_sunset()
- weather_parse_metar in ./
weather_parser.inc - Parses a raw METAR data string
File
- ./
weather_parser.inc, line 482
Code
function _weather_calculate_sunrise_sunset(&$metar) {
$info = weather_get_latitude_longitude($metar['icao']);
// Use gmdate() so times are appropriate for gmmktime() used to
// create new sunrise/sunset times below.
$day_of_year = gmdate('z', $metar['reported_on']);
$year = gmdate('Y', $metar['reported_on']);
$month = gmdate('m', $metar['reported_on']);
$day = gmdate('d', $metar['reported_on']);
// setup pi constants: 0.5*pi, 1.0*pi, 1.5*pi, 2.0*pi
$pi_05 = 1.570796;
$pi_10 = 3.141593;
$pi_15 = 4.712389;
$pi_20 = 6.283185;
// convert latitude and longitude degree into radian
// x rad = y° * pi / 180 = 0.017453 * y°
$latitude = 0.017453 * $info['latitude'];
$longitude = 0.017453 * $info['longitude'];
// we want always GMT time, so set to 0. Otherwise,
// the timezone can be calculated as follows:
// $timezone = 0.261799 * offset;
$timezone = 0;
// the sunrise/sunset altitude in radian (-0.833°)
$altitude = -0.014539;
$sunrise = 0;
$sunset = 0;
foreach (array(
'sunrise' => $pi_05,
'sunset' => $pi_15,
) as $type => $factor) {
$a = $day_of_year + ($factor - $longitude) / $pi_20;
// solar mean anomaly
$sma = $a * 0.017202 - 0.0574039;
// solar true longitude
$stl = $sma + 0.0334405 * sin($sma);
$stl += 4.93289 + 0.000349066 * sin(2 * $sma);
// normalize the longitude to be between >= 0 and < 2.0*pi
while ($stl < 0) {
$stl += $pi_20;
}
while ($stl >= $pi_20) {
$stl -= $pi_20;
}
if ($stl / $pi_05 - intval($stl / $pi_05) == 0) {
$stl += 4.84814E-6;
}
// solar right ascension
$sra = sin($stl) / cos($stl);
$sra = atan2(0.9174600000000001 * $sra, 1);
// adjust quadrant
if ($stl > $pi_15) {
$sra += $pi_20;
}
else {
if ($stl > $pi_05) {
$sra += $pi_10;
}
}
// solar declination
$sd = 0.39782 * sin($stl);
$sd = $sd / sqrt(1 - $sd * $sd);
$sd = atan2($sd, 1);
$diurnal_arc = ($altitude - sin($sd) * sin($latitude)) / (cos($sd) * cos($latitude));
// is there a sunrise or sunset at all?
if ($diurnal_arc >= 1) {
// no sunrise
$no_sunrise = TRUE;
break;
}
if ($diurnal_arc <= -1) {
// no sunset
$no_sunset = TRUE;
break;
}
$diurnal_arc = $diurnal_arc / sqrt(1 - $diurnal_arc * $diurnal_arc);
$diurnal_arc = $pi_05 - atan2($diurnal_arc, 1);
if ($type == 'sunrise') {
$diurnal_arc = $pi_20 - $diurnal_arc;
}
// calculate the time
$localtime = $diurnal_arc + $sra - 0.0172028 * $a - 1.73364;
// wall clock time
$wallclock = $localtime - $longitude + $timezone;
// normalize wallclock to be between >= 0 and < 2.0*pi
while ($wallclock < 0) {
$wallclock += $pi_20;
}
while ($wallclock >= $pi_20) {
$wallclock -= $pi_20;
}
$wallclock = $wallclock * 3.81972;
$hour = intval($wallclock);
$minute = round(($wallclock - $hour) * 60, 0);
if ($type == 'sunrise') {
$sunrise = gmmktime($hour, $minute, 0, $month, $day, $year);
}
else {
$sunset = gmmktime($hour, $minute, 0, $month, $day, $year);
}
}
// handle special cases like no sunrise / sunset at all
if (isset($no_sunset)) {
$condition = 'day';
}
else {
if (isset($no_sunrise)) {
$condition = 'night';
}
else {
// correctly handle northern and southern hemisphere
if ($sunrise <= $sunset) {
// this should be on the northern hemisphere
if ($metar['reported_on'] >= $sunrise and $metar['reported_on'] < $sunset) {
$condition = 'day';
}
else {
$condition = 'night';
}
}
else {
// this should be on the southern hemisphere
if ($metar['reported_on'] >= $sunrise or $metar['reported_on'] <= $sunset) {
$condition = 'day';
}
else {
$condition = 'night';
}
}
}
}
$metar['daytime']['sunrise_on'] = $sunrise;
$metar['daytime']['sunset_on'] = $sunset;
if (isset($no_sunrise)) {
$metar['daytime']['no_sunrise'] = TRUE;
}
else {
$metar['daytime']['no_sunrise'] = FALSE;
}
if (isset($no_sunset)) {
$metar['daytime']['no_sunset'] = TRUE;
}
else {
$metar['daytime']['no_sunset'] = FALSE;
}
$metar['daytime']['condition'] = $condition;
}