You are here

function _weather_sunrise_sunset in Weather 5

Internal helper function to calculate the sunrise and sunset times for a given location

1 call to _weather_sunrise_sunset()
_weather_get_image in ./weather.module

File

./weather.module, line 224
Display <acronym title="METeorological Aerodrome Report">METAR</acronym> weather data from anywhere in the world

Code

function _weather_sunrise_sunset($metar) {

  // Include the ICAO codes
  require_once drupal_get_path('module', 'weather') . '/icao_codes.inc';
  $info = _weather_get_lat_long($metar['icao']);

  // reported_on is already GMT, so don't use gmdate()
  $day_of_year = date('z', $metar['reported_on']);
  $year = date('Y', $metar['reported_on']);
  $month = date('m', $metar['reported_on']);
  $day = date('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['lat'];
  $longitude = 0.017453 * $info['long'];

  // 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 ($no_sunset) {
    $condition = 'day';
  }
  else {
    if ($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';
        }
      }
    }
  }
  return $condition;
}