import { getTimes } from "/vendor/suncalc/suncalc.js"; // A Locus Pro-style toolbar readout: DMS coordinates (plain decimal degrees // read less like a "GPS unit" and are harder to scan at a glance) plus // sunrise/sunset and a countdown to whichever comes next — both computed // for the map's current center, the same point the coordinates already // describe, not a GNSS fix (this app's coordinate readout was never tied // to having one). function toDMS(value, positiveLabel, negativeLabel) { const label = value >= 0 ? positiveLabel : negativeLabel; const abs = Math.abs(value); const degrees = Math.floor(abs); const minutesFull = (abs - degrees) * 60; let minutes = Math.floor(minutesFull); let seconds = Math.round((minutesFull - minutes) * 60); // A seconds value that rounds up to 60 has to carry into minutes (and // from there, in the rare case, into degrees) rather than print "60". if (seconds === 60) { seconds = 0; minutes += 1; } const carriedDegrees = minutes === 60 ? degrees + 1 : degrees; const carriedMinutes = minutes === 60 ? 0 : minutes; return `${carriedDegrees}°${String(carriedMinutes).padStart(2, "0")}'${String(seconds).padStart(2, "0")}"${label}`; } export function formatCoords(lat, lng) { return `${toDMS(lat, "N", "S")} ${toDMS(lng, "E", "W")}`; } function formatTime(date) { return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`; } function formatCountdown(ms) { const totalMinutes = Math.max(0, Math.round(ms / 60000)); const hours = Math.floor(totalMinutes / 60); const minutes = totalMinutes % 60; return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`; } const DAY_MS = 24 * 60 * 60 * 1000; // null when there's no sunrise/sunset to show at all — getTimes returns // null (not Invalid Date) for both on a polar day/night, per its own // comment in suncalc.js — the caller just hides the readout in that case // rather than showing something misleading. export function formatSunInfo(lat, lng, now = new Date()) { const today = getTimes(now, lat, lng); if (today.sunrise === null || today.sunset === null) return null; let next; if (now < today.sunrise) { next = { label: "sunrise", at: today.sunrise }; } else if (now < today.sunset) { next = { label: "sunset", at: today.sunset }; } else { // Already past today's sunset — the next event is tomorrow's sunrise. const tomorrow = getTimes(new Date(now.getTime() + DAY_MS), lat, lng); next = tomorrow.sunrise === null ? null : { label: "sunrise", at: tomorrow.sunrise }; } const countdown = next ? ` · ${formatCountdown(next.at - now)} to ${next.label}` : ""; return `${formatTime(today.sunrise)}–${formatTime(today.sunset)}${countdown}`; }