getSunriseSunset function

SunriseSunsetResult getSunriseSunset(
  1. double latitude,
  2. double longitude,
  3. Duration utcOffset,
  4. DateTime date,
)

GetSunriseSunset function is responsible for calculating the apparent Sunrise and Sunset times. If some parameter is wrong it will throw an error.

Implementation

SunriseSunsetResult getSunriseSunset(
    double latitude, double longitude, Duration utcOffset, DateTime date) {
  // Check latitude
  if (!checkLatitude(latitude)) {
    throw Exception('Invalid latitude');
  }
  // Check longitude
  if (!checkLongitude(longitude)) {
    throw Exception('Invalid longitude');
  }
  // Check UTC offset
  if (!checkUtcOffset(utcOffset.inHours)) {
    throw Exception('Invalid UTC offset');
  }
  // Check date
  if (!checkDate(date)) {
    throw Exception('Invalid Date');
  }

  // The doubleber of days since 30/12/1899
  final since = DateTime.utc(1899, 12, 30);
  final doubleDays = date.difference(since).inDays;

  // Seconds of a full day 86400
  const seconds = secondsInADay;
  final utcOffsetHours = date.timeZoneOffset.inHours / 24;

  // Creates a vector that represents each second in the range 0~1
  final secondsNorm = _createSecondsNormalized(seconds);

  // Calculate Julian Day
  final julianDay = secondsNorm
      .map((seconds) => calcJulianDay(doubleDays, seconds, utcOffsetHours));

  // Calculate Julian Century
  final julianCentury = julianDay.map(calcJulianCentury).toList();

  // Geom Mean Long Sun (deg)
  final geomMeanLongSun = julianCentury.map(calcGeomMeanLongSun).toList();

  // Geom Mean Anom Sun (deg)
  final geomMeanAnomSun = julianCentury.map(calcGeomMeanAnomSun).toList();

  // Eccent Earth Orbit
  final eccentEarthOrbit = julianCentury.map(calcEccentEarthOrbit).toList();

  // Sun Eq of Ctr
  final sunEqCtr = List<double>.generate(julianCentury.length,
      (index) => calcSunEqCtr(julianCentury[index], geomMeanAnomSun[index]));

  // Sun True Long (deg)
  final sunTrueLong = List<double>.generate(sunEqCtr.length,
      (index) => calcSunTrueLong(sunEqCtr[index], geomMeanLongSun[index]));

  // Sun App Long (deg)
  final sunAppLong = List<double>.generate(sunTrueLong.length,
      (index) => calcSunAppLong(sunTrueLong[index], julianCentury[index]));

  // Mean Obliq Ecliptic (deg)
  final meanObliqEcliptic = julianCentury.map(calcMeanObliqEcliptic).toList();

  // Obliq Corr (deg)
  final obliqCorr = List<double>.generate(julianCentury.length,
      (index) => calcObliqCorr(meanObliqEcliptic[index], julianCentury[index]));

  // Sun Declin (deg)
  final sunDeclination = List<double>.generate(obliqCorr.length,
      (index) => calcSunDeclination(obliqCorr[index], sunAppLong[index]));

  final multiFactor = obliqCorr.map(calcMultiFactoror).toList();

  // Eq of Time (minutes)
  final equationOfTime = List<double>.generate(
      multiFactor.length,
      (index) => calcEquationOfTime(multiFactor[index], geomMeanLongSun[index],
          eccentEarthOrbit[index], geomMeanAnomSun[index])).toList();

  // HA Sunrise (deg)
  final haSunrise = List<double>.generate(sunDeclination.length,
      (index) => calcHaSunrise(latitude, sunDeclination[index]));

  // Solar Noon (LST)
  final solarNoon = List<double>.generate(
      equationOfTime.length,
      (index) =>
          calcSolarNoon(longitude, equationOfTime[index], utcOffset.inHours));

  // Sunrise and Sunset Times (LST)
  var minSunrise = 86400.0;
  var sunriseSeconds = -1;
  var minSunset = 86400.0;
  var sunsetSeconds = -1;
  int a;
  double b;

  for (var index = 0; index < solarNoon.length; index++) {
    a = (haSunrise[index] * 4.0 * 60.0).round();
    b = seconds * secondsNorm[index];

    var sunrise = (solarNoon[index] - a - b).abs();
    var sunset = (solarNoon[index] + a - b).abs();

    if (sunrise < minSunrise) {
      minSunrise = sunrise;
      sunriseSeconds = index;
    }
    if (sunset < minSunset) {
      minSunset = sunset;
      sunsetSeconds = index;
    }
  }

  // Convert the seconds to time
  final defaultTime = DateTime.utc(date.year, date.month, date.day, 0, 0, 0);
  return SunriseSunsetResult(defaultTime.add(Duration(seconds: sunriseSeconds)),
      defaultTime.add(Duration(seconds: sunsetSeconds)));
}