diff --git a/astro.html b/astro.html
index aa2fbd7..ff8e2d6 100644
--- a/astro.html
+++ b/astro.html
@@ -35,16 +35,28 @@
color: var(--muted);
margin-top: 0.2rem;
}
+ .astro-head {
+ display: grid;
+ grid-template-columns: 130px 1fr 1fr;
+ gap: 0.35rem 0.9rem;
+ font-size: 0.72rem;
+ color: #808892;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ margin-top: 0.35rem;
+ }
.astro-grid {
display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 0.4rem 1rem;
- font-size: 0.92rem;
+ grid-template-columns: 130px 1fr 1fr;
+ gap: 0.35rem 0.9rem;
+ font-size: 0.9rem;
color: var(--muted);
- margin: 1.2rem 0;
+ margin: 0.45rem 0 1.1rem;
+ }
+ .astro-label {
+ color: var(--text);
+ font-weight: 600;
}
- .astro-grid p { margin: 0; }
- .astro-grid strong { color: var(--text); }
.date-nav {
display: flex;
align-items: center;
@@ -92,10 +104,19 @@
border-bottom: 1px solid #2a2a2a;
display: flex;
justify-content: space-between;
+ align-items: flex-start;
gap: 0.5rem;
}
.event-list li:last-child { border-bottom: none; }
.event-name { color: var(--text); }
+ .event-dual {
+ display: flex;
+ flex-direction: column;
+ text-align: right;
+ gap: 0.04rem;
+ font-size: 0.77rem;
+ }
+ .event-dual span:first-child { color: var(--text); }
@@ -117,19 +138,23 @@
—
+
+
Sun
-
Sunrise: —
-
Sunset: —
-
Day length: —
-
Solar noon: —
+
Sunrise
—
—
+
Sunset
—
—
+
Day length
—
—
+
Solar noon
—
—
Moon
-
Age: —
-
Next new moon: —
-
Next full moon: —
+
Age
—
—
+
Next new moon
—
—
+
Next full moon
—
—
diff --git a/astro.js b/astro.js
index 8d20c36..470394c 100644
--- a/astro.js
+++ b/astro.js
@@ -143,6 +143,54 @@ function dayLengthStr(riseJD, setJD) {
return `${h}h ${String(m).padStart(2,"0")}m`;
}
+function jdToDecimalTime(jd) {
+ const frac = ((jd + 0.5) % 1 + 1) % 1;
+ const dec = frac * 10;
+ const h = Math.floor(dec);
+ const m = Math.floor((dec - h) * 100);
+ return `${h}:${String(m).padStart(2, "0")}`;
+}
+
+function dayLengthDecimalStr(riseJD, setJD) {
+ const decHours = (setJD - riseJD) * 10;
+ const h = Math.floor(decHours);
+ const m = Math.floor((decHours - h) * 100);
+ return `${h}:${String(m).padStart(2, "0")}`;
+}
+
+// ── Seth date helpers ───────────────────────────────────────────────────────
+function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+}
+
+function getDayOfYearUTC(date) {
+ const y = date.getUTCFullYear();
+ const m = date.getUTCMonth() + 1;
+ const d = date.getUTCDate();
+ const cum = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
+ let doy = cum[m - 1] + d;
+ if (isLeapYear(y) && m > 2) doy++;
+ return { year: y, doy };
+}
+
+function toSethDate(year, dayOfYear) {
+ const leap = isLeapYear(year);
+ if (leap && dayOfYear === 60) return { type: "leapday", year };
+ const idx = (leap && dayOfYear > 60 ? dayOfYear - 1 : dayOfYear) - 1;
+ if (idx < 360) {
+ const month = Math.floor(idx / 36);
+ const dayInM = idx % 36;
+ return { type: "month", year, month, day: dayInM };
+ }
+ return { type: "holiday", year, holiday: idx - 360 };
+}
+
+function sethLog(sd) {
+ if (sd.type === "leapday") return `Leap Day ${sd.year}`;
+ if (sd.type === "holiday") return `H${sd.holiday}.${sd.year}`;
+ return `${String(sd.day).padStart(2, "0")}.${sd.month}.${sd.year}`;
+}
+
// ── Solstice / Equinox (Meeus Table 27.a + correction) ───────────────────────
// Returns approximate JD for each event in a given year
// season: 0=March equinox, 1=June solstice, 2=September equinox, 3=December solstice
@@ -246,15 +294,27 @@ function render() {
const jd = jdFromDate(date);
const nextNewJD = nextMoonPhaseJD(jd, 0);
const nextFullJD = nextMoonPhaseJD(jd, 2);
- document.getElementById("nextNew").textContent = dateFromJD(nextNewJD).toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
- document.getElementById("nextFull").textContent = dateFromJD(nextFullJD).toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
+ const nextNewDate = dateFromJD(nextNewJD);
+ const nextFullDate = dateFromJD(nextFullJD);
+ const nextNewSeth = toSethDate(getDayOfYearUTC(nextNewDate).year, getDayOfYearUTC(nextNewDate).doy);
+ const nextFullSeth = toSethDate(getDayOfYearUTC(nextFullDate).year, getDayOfYearUTC(nextFullDate).doy);
+ document.getElementById("nextNewSeth").textContent = sethLog(nextNewSeth);
+ document.getElementById("nextNewGreg").textContent = nextNewDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", timeZone: "UTC" });
+ document.getElementById("nextFullSeth").textContent = sethLog(nextFullSeth);
+ document.getElementById("nextFullGreg").textContent = nextFullDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", timeZone: "UTC" });
// Sun
const sun = sunriseSunset(date, LAT, LON);
- document.getElementById("sunrise").textContent = sun.rise || (sun.alwaysUp ? "Midnight sun" : "Below horizon");
- document.getElementById("sunset").textContent = sun.set || (sun.alwaysUp ? "Midnight sun" : "Below horizon");
- document.getElementById("solarNoon").textContent = sun.noon;
- document.getElementById("dayLen").textContent = sun.rise && sun.set ? dayLengthStr(sun.riseJD, sun.setJD) : "—";
+ document.getElementById("sunriseSeth").textContent = sun.riseJD ? jdToDecimalTime(sun.riseJD) : "—";
+ document.getElementById("sunriseGreg").textContent = sun.rise || (sun.alwaysUp ? "Midnight sun" : "Below horizon");
+ document.getElementById("sunsetSeth").textContent = sun.setJD ? jdToDecimalTime(sun.setJD) : "—";
+ document.getElementById("sunsetGreg").textContent = sun.set || (sun.alwaysUp ? "Midnight sun" : "Below horizon");
+ document.getElementById("solarNoonSeth").textContent = sun.noonJD ? jdToDecimalTime(sun.noonJD) : "—";
+ document.getElementById("solarNoonGreg").textContent = sun.noon;
+ document.getElementById("dayLenSeth").textContent = sun.rise && sun.set ? dayLengthDecimalStr(sun.riseJD, sun.setJD) : "—";
+ document.getElementById("dayLenGreg").textContent = sun.rise && sun.set ? dayLengthStr(sun.riseJD, sun.setJD) : "—";
+ document.getElementById("moonAgeSeth").textContent = `${(age * (10 / 29.53058867)).toFixed(2)} days`;
+ document.getElementById("moonAgeGreg").textContent = `${age.toFixed(1)} days`;
@@ -290,9 +350,12 @@ function render() {
ul.innerHTML = "";
allEvents.forEach(ev => {
const li = document.createElement("li");
- const ds = ev.date.toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
+ const ds = ev.date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", timeZone: "UTC" });
+ const sy = getDayOfYearUTC(ev.date);
+ const sseth = toSethDate(sy.year, sy.doy);
+ const sds = sethLog(sseth);
const isToday = dateToParam(ev.date) === dateToParam(date);
- li.innerHTML = `${ev.name}${ds}`;
+ li.innerHTML = `${ev.name}${sds}${ds}`;
ul.appendChild(li);
});
}