Files
SRS IT 27be1892ed Initial release — Dibby Wemo Manager v2.0.0
Desktop (Electron/Windows): device dashboard, DWM scheduling engine,
native firmware rules editor, Windows background service, web remote,
sunrise/sunset support.

Homebridge plugin (homebridge-dibby-wemo v1.0.0): HomeKit switches for
all local Wemo devices, custom UI with DWM rules, device rules,
scheduler heartbeat, and location-based sunrise/sunset scheduling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 16:30:43 -04:00

82 lines
2.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/**
* Calculate sunrise and sunset times for a given location and date.
* Pure JS no external dependencies.
*
* Algorithm: NOAA Solar Calculator (Jean Meeus, Astronomical Algorithms).
*
* @param {number} lat Latitude in decimal degrees (positive = North)
* @param {number} lng Longitude in decimal degrees (positive = East)
* @param {Date} date Date to calculate for (default: today)
* @returns {{ sunrise: number|null, sunset: number|null }}
* Times as integer seconds from LOCAL midnight.
* null for each value if polar day or polar night.
*/
function sunTimes(lat, lng, date = new Date()) {
const D2R = Math.PI / 180;
const R2D = 180 / Math.PI;
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const A = Math.floor((14 - month) / 12);
const Y = year + 4800 - A;
const M = month + 12 * A - 3;
const JDN = day + Math.floor((153 * M + 2) / 5) + 365 * Y
+ Math.floor(Y / 4) - Math.floor(Y / 100) + Math.floor(Y / 400) - 32045;
const JD = JDN - 0.5;
const T = (JD - 2451545.0) / 36525.0;
let L0 = 280.46646 + T * (36000.76983 + T * 0.0003032);
L0 = ((L0 % 360) + 360) % 360;
let Mdeg = 357.52911 + T * (35999.05029 - 0.0001537 * T);
Mdeg = ((Mdeg % 360) + 360) % 360;
const Mrad = Mdeg * D2R;
const C = (1.914602 - T * (0.004817 + 0.000014 * T)) * Math.sin(Mrad)
+ (0.019993 - 0.000101 * T) * Math.sin(2 * Mrad)
+ 0.000289 * Math.sin(3 * Mrad);
const omega = 125.04 - 1934.136 * T;
const lambda = (L0 + C) - 0.00569 - 0.00478 * Math.sin(omega * D2R);
const eps0 = 23.0
+ (26.0 + (21.448 - T * (46.8150 + T * (0.00059 - T * 0.001813))) / 60.0) / 60.0;
const eps = (eps0 + 0.00256 * Math.cos(omega * D2R)) * D2R;
const sinDec = Math.sin(eps) * Math.sin(lambda * D2R);
const decl = Math.asin(sinDec);
const e = 0.016708634 - T * (0.000042037 + 0.0000001267 * T);
const y = Math.pow(Math.tan(eps / 2), 2);
const EqT = 4 * R2D * (
y * Math.sin(2 * L0 * D2R)
- 2 * e * Math.sin(Mrad)
+ 4 * e * y * Math.sin(Mrad) * Math.cos(2 * L0 * D2R)
- 0.5 * y * y * Math.sin(4 * L0 * D2R)
- 1.25 * e * e * Math.sin(2 * Mrad)
);
const cosHA = (Math.cos(90.833 * D2R) - Math.sin(lat * D2R) * sinDec)
/ (Math.cos(lat * D2R) * Math.cos(decl));
if (cosHA < -1 || cosHA > 1) {
return { sunrise: null, sunset: null };
}
const HA = Math.acos(cosHA) * R2D;
const tzOffsetMin = -date.getTimezoneOffset();
const solarNoon = 720.0 - 4.0 * lng - EqT + tzOffsetMin;
return {
sunrise: Math.round((solarNoon - HA * 4.0) * 60),
sunset: Math.round((solarNoon + HA * 4.0) * 60),
};
}
module.exports = { sunTimes };