getMoonTimes static method
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;
}