getMoonTimes static method

Map getMoonTimes(
  1. DateTime date,
  2. num lat,
  3. num lng, [
  4. bool inUtc = true,
])

Implementation

static Map getMoonTimes(DateTime date, num lat, num lng,
    [bool inUtc = true]) {
  var t = DateTime(date.year, date.month, date.day, 0, 0, 0);
  if (inUtc) {
    t = DateTime.utc(date.year, date.month, date.day, 0, 0, 0);
  }
  const hc = 0.133 * rad;
  var h0 = (SunCalc.getMoonPosition(t, lat, lng)["altitude"] ?? 0.0) - hc;
  var h1 = 0.0;
  var h2 = 0.0;
  var rise = 0.0;
  var set = 0.0;
  var a = 0.0;
  var b = 0.0;
  var xe = 0.0;
  var ye = 0.0;
  var d = 0.0;
  var roots = 0.0;
  var x1 = 0.0;
  var x2 = 0.0;
  var dx = 0.0;

  // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set)
  for (var i = 1; i <= 24; i += 2) {
    h1 = (SunCalc.getMoonPosition(hoursLater(t, i), lat, lng)["altitude"] ??
            0) -
        hc;
    h2 = (SunCalc.getMoonPosition(
                hoursLater(t, i + 1), lat, lng)["altitude"] ??
            0) -
        hc;

    a = (h0 + h2) / 2 - h1;
    b = (h2 - h0) / 2;
    xe = -b / (2 * a);
    ye = (a * xe + b) * xe + h1;
    d = b * b - 4 * a * h1;
    roots = 0;

    if (d >= 0) {
      dx = math.sqrt(d) / (a.abs() * 2);
      x1 = xe - dx;
      x2 = xe + dx;
      if (x1.abs() <= 1) roots++;
      if (x2.abs() <= 1) roots++;
      if (x1 < -1) x1 = x2;
    }

    if (roots == 1) {
      if (h0 < 0) {
        rise = i + x1;
      } else {
        set = i + x1;
      }
    } else if (roots == 2) {
      rise = i + (ye < 0 ? x2 : x1);
      set = i + (ye < 0 ? x1 : x2);
    }

    if ((rise != 0) && (set != 0)) {
      break;
    }

    h0 = h2;
  }

  var result = {};
  result["alwaysUp"] = false;
  result["alwaysDown"] = false;

  if (rise != 0) {
    result["rise"] = hoursLater(t, rise);
  }
  if (set != 0) {
    result["set"] = hoursLater(t, set);
  }

  if ((rise == 0) && (set == 0)) {
    result[ye > 0 ? "alwaysUp" : "alwaysDown"] = true;
  }

  return result;
}