<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Open Waters: Sky updates</title>
    <link>https://openwaters.io/updates/sky/</link>
    <atom:link href="https://openwaters.io/updates/sky/rss.xml" rel="self" type="application/rss+xml" />
    <description>New releases and announcements from Sky.</description>
    <language>en</language>
    <item>
      <title>Earth perihelion and aphelion (Almanac 0.11.0)</title>
      <link>https://openwaters.io/updates/almanac-0-11-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-11-0/</guid>
      <pubDate>Sun, 18 Oct 2026 13:05:46 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.11.0 adds Earth perihelion and aphelion events in TypeScript, Swift, and Kotlin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;earthApsides(startUtc, endUtc)&lt;/code&gt; / &lt;code&gt;earthApsides(from:to:)&lt;/code&gt; returns the sorted perihelion and aphelion events in a half-open window. Each carries its time, its kind (&lt;code&gt;perihelion&lt;/code&gt; or &lt;code&gt;aphelion&lt;/code&gt;; &lt;code&gt;EarthApsisKind&lt;/code&gt; in Swift and Kotlin), and &lt;code&gt;distanceKm&lt;/code&gt;, the geometric Sun–Earth centre distance at that instant.&lt;/li&gt;
&lt;li&gt;The search brackets each root in fixed cells anchored at J2000, as the season and lunar apsis searches do, so every window containing an event reports the same millisecond.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.11.0/docs/CONTRACT.md&quot;&gt;contract&lt;/a&gt; defines the model and tolerances, and the README shows the call in each language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The search translates Astronomy Engine&amp;#39;s &lt;code&gt;SearchPlanetApsis&lt;/code&gt; for Earth. A pinned, independently compiled Astronomy Engine run is committed as an implementation oracle for all 302 events from 1950 through 2100. Every event matches, with a worst timing difference of 1.525 seconds and a distance difference below a millimeter, against tolerances of 2 seconds and 1 meter. This verifies the translation; it makes no separate physical-accuracy claim. Cross-port parity checks the new events in all three ports, and the release workflow verifies all three suites, Kotlin coverage and source consumption, and independent SwiftPM and packed npm consumers before publishing with provenance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.11.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;import { earthApsides } from &amp;#39;@openwaters/almanac&amp;#39;;
for (const { kind, time, distanceKm } of earthApsides(start, end)) console.log(kind, time.toISOString(), distanceKm);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.11.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin consumers can pin the &lt;code&gt;v0.11.0&lt;/code&gt; source checkout using the &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.11.0/kotlin/README.md&quot;&gt;installation guide&lt;/a&gt;. No Maven artifact is published.&lt;/p&gt;
&lt;p&gt;Earth apsides: #82. CI Node versions from mise: #80. Release preparation: #83.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.10.0...v0.11.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Open Waters updates</title>
      <link>https://openwaters.io/updates/open-waters-updates/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/open-waters-updates/</guid>
      <pubDate>Sun, 18 Oct 2026 00:00:00 GMT</pubDate>
      <category>Announcement</category>
      <description>&lt;p&gt;Welcome to Open Waters &lt;a href=&quot;https://openwaters.io/updates/&quot;&gt;Updates&lt;/a&gt;, a feed of all our project releases and announcements. If you only care about one topic, you can filter releases and announcements by project: &lt;a href=&quot;https://openwaters.io/updates/ais/&quot;&gt;AIS&lt;/a&gt;, &lt;a href=&quot;https://openwaters.io/updates/tides/&quot;&gt;Tides &amp;amp; Currents&lt;/a&gt;, &lt;a href=&quot;https://openwaters.io/updates/charts/&quot;&gt;Charts&lt;/a&gt;, and &lt;a href=&quot;https://openwaters.io/updates/sky/&quot;&gt;Sky&lt;/a&gt;. You can also show only &lt;a href=&quot;https://openwaters.io/updates/announcements/&quot;&gt;announcements&lt;/a&gt; or only &lt;a href=&quot;https://openwaters.io/updates/releases/&quot;&gt;releases&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Every page has an RSS feed. Add &lt;a href=&quot;https://openwaters.io/updates/announcements/rss.xml&quot;&gt;the announcements feed&lt;/a&gt; to your reader if you only want the big news, or a project’s release feed, such as &lt;a href=&quot;https://openwaters.io/updates/ais/releases/rss.xml&quot;&gt;AIS releases&lt;/a&gt;, if you build on it.&lt;/p&gt;
&lt;p&gt;Questions or ideas? Find us on &lt;a href=&quot;https://discord.gg/NeMyrYMGr&quot;&gt;Discord&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Requires Swift 6 (Almanac 0.10.0)</title>
      <link>https://openwaters.io/updates/almanac-0-10-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-10-0/</guid>
      <pubDate>Tue, 13 Oct 2026 08:34:39 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.10.0 uses Swift 6 language mode and requires a Swift 6 or newer toolchain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Swift&amp;#39;s compiler checks the package and its tests under Swift 6 concurrency rules. Immutable event specifications have a checked Sendable conformance.&lt;/li&gt;
&lt;li&gt;The public astronomy API and calculations are unchanged. TypeScript and Kotlin consumers use the same API as 0.9.0.&lt;/li&gt;
&lt;li&gt;Slackwater&amp;#39;s iOS consumer validation passed Debug and unsigned Release builds for the phone, watch, and both widget extensions, including watch hardware&amp;#39;s arm64_32 architecture. All 170 selected sun, moon, eclipse, alert, and timeline integration tests passed.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.10.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.10.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin consumers can pin the &lt;code&gt;v0.10.0&lt;/code&gt; source checkout using the &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.10.0/kotlin/README.md&quot;&gt;installation guide&lt;/a&gt;. No Maven artifact is published.&lt;/p&gt;
&lt;p&gt;Swift 6 migration: #78. Release preparation: #79.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.9.0...v0.10.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Check whether the Sun is up (Almanac 0.9.0)</title>
      <link>https://openwaters.io/updates/almanac-0-9-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-9-0/</guid>
      <pubDate>Mon, 12 Oct 2026 21:45:17 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.9.0 provides an instantaneous sunrise-based day/night decision in TypeScript, Swift, and Kotlin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sunIsUp(time, observer, heightAboveGroundM = 0)&lt;/code&gt; returns whether the Sun’s upper limb clears the modeled horizon. It uses the same changing solar radius, standard refraction convention, topocentric geometry, and optional horizon dip as &lt;code&gt;sunEvents&lt;/code&gt; sunrise and sunset.&lt;/li&gt;
&lt;li&gt;Polar day and night work without an event search or a calendar-day choice. The helper preserves the existing date, observer, and eye-height validation. Exact equality with the horizon target returns &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.9.0/docs/cookbook.md&quot;&gt;cookbook&lt;/a&gt; shows display-mode recipes in all three languages, explains eye height versus elevation, and leaves refresh timing and missing-position handling to the application. The astronomical model does not account for terrain, clouds, or eclipses.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tests cover independent USNO sunrise/set evidence, midnight sun, polar night, raised horizons, and a grazing polar sunrise where a fixed threshold on refracted altitude reports night. Cross-port parity checks the boolean exactly. The release workflow verifies all three suites, Kotlin coverage and source consumption, and independent SwiftPM and packed npm consumers before publishing with provenance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.9.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;import { sunIsUp } from &amp;#39;@openwaters/almanac&amp;#39;;
const mode = sunIsUp(new Date(), observer) ? &amp;#39;day&amp;#39; : &amp;#39;night&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.9.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin consumers can pin the &lt;code&gt;v0.9.0&lt;/code&gt; source checkout using the &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.9.0/kotlin/README.md&quot;&gt;installation guide&lt;/a&gt;. No Maven artifact is published.&lt;/p&gt;
&lt;p&gt;Day/night helper and cookbook: #75. Release preparation: #76.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.8.1...v0.9.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Kotlin port, angle helpers, and tested migration guides (Almanac 0.8.1)</title>
      <link>https://openwaters.io/updates/almanac-0-8-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-8-1/</guid>
      <pubDate>Mon, 12 Oct 2026 14:51:19 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.8.1 provides shared angle conversion helpers and tested migration guides, with the public astronomy API available in TypeScript, Swift, and Kotlin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;degreesToRadians&lt;/code&gt; and &lt;code&gt;radiansToDegrees&lt;/code&gt; preserve signed angles and full turns without wrapping. Non-finite inputs and conversion overflow raise validation errors.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/docs/migrating-from-suncalc.md&quot;&gt;SunCalc guide&lt;/a&gt; and &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/docs/migrating-from-astronomy-engine.md&quot;&gt;Astronomy Engine guide&lt;/a&gt; cover event windows, polar crossings, refraction, phase conventions, and supported-range boundaries, with tested examples.&lt;/li&gt;
&lt;li&gt;The native Kotlin/JVM port shares the public contract and fixture corpus with TypeScript and Swift. It supports Java 8 bytecode and Android API 26+, and is consumed through a &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/kotlin/README.md&quot;&gt;pinned source checkout&lt;/a&gt;; no Maven artifact is published.&lt;/li&gt;
&lt;li&gt;Equinox and solstice searches, lunar perigee and apogee searches, and the equation of time are available in all three ports. The &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.1/docs/CONTRACT.md&quot;&gt;accuracy contract&lt;/a&gt; records their evidence and limits: measured worst errors are 79 seconds for seasons through 2050, 14.8 minutes and 54 kilometers for lunar apsides, and 1.0 second for the equation of time.&lt;/li&gt;
&lt;li&gt;The packed npm package is checked with static ESM imports, dynamic imports, and synchronous CommonJS loading on Node 22.12 and 24.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Local validation for the conversion helpers and guides passed 245 TypeScript tests, 204 Swift release tests, and 79 Kotlin tests, with 100% handwritten Kotlin line coverage. The release workflow runs all three suites, fixture checks, and independent npm and SwiftPM consumers before publishing.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.8.1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.8.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Angle helpers and migration guides: #73. Kotlin port: #70. Seasons, apsides, and equation of time: #68. Benchmarks: #69. Release preparation: #74.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.8.0...v0.8.1&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Uranus and Neptune, plus guides for moving from SunCalc and Solar (Almanac 0.8.0)</title>
      <link>https://openwaters.io/updates/almanac-0-8-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-8-0/</guid>
      <pubDate>Sun, 11 Oct 2026 03:43:06 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.8.0 adds Uranus and Neptune, the Sun and Moon events apps need to move off SunCalc, and migration guides for SunCalc and Solar, in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sunAltitudeEvents(startUtc, endUtc, observer, altitudeDeg)&lt;/code&gt; finds the Sun crossing any altitude, rising and falling: golden hour at +6°, blue hour, or SunCalc&amp;#39;s &lt;code&gt;addTime&lt;/code&gt; angles, which mean the same thing here. At −6° it returns the same instants as civil twilight.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sunTransits&lt;/code&gt; and &lt;code&gt;moonTransits&lt;/code&gt; find upper and lower transits, so solar midnight and the Moon&amp;#39;s highest and lowest points are available alongside rise and set.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;moonOrientation(time, observer)&lt;/code&gt; gives the position angle of the Moon&amp;#39;s bright limb and its parallactic angle; subtracting one from the other gives the bright limb&amp;#39;s angle from the zenith, which is what drawing the Moon as it looks needs.&lt;/li&gt;
&lt;li&gt;Uranus and Neptune support every planetary API: Sun-centered vectors, apparent positions, altitude and azimuth, illumination, approximate magnitude, solar elongation, and rise and set.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.0/docs/migrating-from-suncalc.md&quot;&gt;Migrating from SunCalc&lt;/a&gt; and &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.0/docs/migrating-from-solar.md&quot;&gt;Migrating from Solar&lt;/a&gt; map every export of those libraries to an Almanac call and give drop-in adapters; both test suites run the guides&amp;#39; code verbatim against output recorded from SunCalc 2.1.1 and Solar 4.0.1. &lt;a href=&quot;https://github.com/openwatersio/almanac/blob/v0.8.0/docs/comparison.md&quot;&gt;How Almanac compares&lt;/a&gt; sets it beside SunCalc, Astronomy Engine, astronomia, Solar, SwiftAA, and EDSunriseSet, including where they are the better choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existing functions return the same results, and no existing enum gains a case.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;New quantity&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sun altitude crossings at +6°, −0.3°, −4°, −8°&lt;/td&gt;
&lt;td&gt;124 crossings on Horizons one-minute grids, 20°N to 70.5°N&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5.6 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upper and lower transits, Sun and Moon&lt;/td&gt;
&lt;td&gt;Horizons hour-angle grids&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.1 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moon upper transit, Sun and Moon lower transit&lt;/td&gt;
&lt;td&gt;54 USNO rows&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;27.5 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallactic angle&lt;/td&gt;
&lt;td&gt;Horizons azimuth, elevation, and declination&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.18′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bright limb, elongation 20°–160°&lt;/td&gt;
&lt;td&gt;Meeus 48.5 on Horizons apparent positions&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.42′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uranus, Neptune Sun-centered position&lt;/td&gt;
&lt;td&gt;Horizons, 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.00035 AU&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.001 AU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Against SunCalc 2.1.1 the migration adapters agree within 7 seconds on Sun times and 4 seconds on moonrise and moonset. Against Solar 4.0.1 they agree within 59 seconds from 34°S to 49°N; at 78°N, where the Sun grazes the twilight altitudes, the worst is 449 seconds.&lt;/p&gt;
&lt;p&gt;Validation includes 216 TypeScript tests, 178 Swift release tests, offline fixture regeneration, cross-port parity, and Apple Watch compilation. Every existing benchmark workload stays inside the 20% regression limit. A year of Sun altitude events takes about 21 ms in TypeScript and 12 ms in Swift, and a year of Sun or Moon transits about 7 ms and 4 ms; timings vary by machine.&lt;/p&gt;
&lt;p&gt;Fixture metadata records each Horizons request&amp;#39;s own retrieval date, checked against the raw response headers.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.8.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.8.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Uranus and Neptune: #59. SunCalc parity and migration guide: #62. Solar migration guide: #65. Library comparison: #64. CI lockfile checks: #60, #66. Release preparation: #67.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.7.0...v0.8.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Horizon dip and planetary motion (Almanac 0.7.0)</title>
      <link>https://openwaters.io/updates/almanac-0-7-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-7-0/</guid>
      <pubDate>Tue, 06 Oct 2026 17:57:02 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.7.0 provides apparent horizon dip and native planetary motion in TypeScript and Swift, with Earth included for solar-system views.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;horizonDip(observer, heightAboveGroundM)&lt;/code&gt; gives the apparent altitude of an unobstructed horizon, accounting for Earth shape and terrestrial refraction. Eye height above the surface is separate from elevation above sea level; body altitudes remain relative to the horizontal plane.&lt;/li&gt;
&lt;li&gt;Sun and Moon rise/set, local solar eclipse searches, and lunar eclipse visibility accept optional eye height. The default of zero preserves existing calls and results. Twilight and transit retain their definitions.&lt;/li&gt;
&lt;li&gt;Mercury, Venus, Mars, Jupiter, and Saturn have apparent positions, refracted altitude/azimuth, point-center rise/set, illumination, approximate airless visual magnitude, and solar elongation through &lt;code&gt;planetPosition&lt;/code&gt;, &lt;code&gt;planetAltAz&lt;/code&gt;, &lt;code&gt;planetEvents&lt;/code&gt;, and &lt;code&gt;planetIllumination&lt;/code&gt;. Viewing windows combine these quantities with the consumer&amp;#39;s twilight and observing policy.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;planetHeliocentricPosition&lt;/code&gt; accepts those five planets and Earth. It returns geometric Sun-centered &lt;code&gt;xAu&lt;/code&gt;, &lt;code&gt;yAu&lt;/code&gt;, and &lt;code&gt;zAu&lt;/code&gt; in fixed J2000 equatorial coordinates. Earth-based planetary queries reject Earth.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Planetary geometry is checked against JPL Horizons across 1950 through 2100, including both supported boundaries, conjunctions, near-zenith tracks, and polar grazing rise/set pairs. Angular limits remain one arcminute, physical range and heliocentric vector limits are 0.001 AU, and event limits are 60 seconds. Magnitudes are approximate: the pinned model differs from Horizons by up to 0.75 magnitudes for extreme Venus crescents in the retained evidence. Saturn&amp;#39;s magnitude includes its rings.&lt;/p&gt;
&lt;p&gt;Validation includes 193 TypeScript tests, 155 Swift release tests, offline fixture regeneration, cross-port reproduction within 5 scaled units / 100 ms, and Apple Watch hardware and simulator compilation. All 30 benchmark workloads pass the 20% regression limit in both ports. On the local machine, the five-planet 228-hour sky track takes about 17.2 ms in TypeScript and 6.5 ms in Swift; timings vary by machine.&lt;/p&gt;
&lt;p&gt;The library retains zero runtime dependencies and zero runtime data files. Plans and specs live in #51; the repository contains the maintained API contract and scope.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.7.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.7.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Documentation scope: #50. Apparent horizon: #52. Planetary motion: #53. Release preparation: #55.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.6.0...v0.7.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Where each solar eclipse is greatest (Almanac 0.6.0)</title>
      <link>https://openwaters.io/updates/almanac-0-6-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-6-0/</guid>
      <pubDate>Sun, 27 Sep 2026 22:12:39 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.6.0 reports where greatest eclipse falls for every solar eclipse on Earth, including partial eclipses, in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GlobalSolarEclipse&lt;/code&gt; gains &lt;code&gt;greatestLatitudeDeg&lt;/code&gt;, &lt;code&gt;greatestLongitudeDeg&lt;/code&gt;, and &lt;code&gt;greatestObscuration&lt;/code&gt;, present for every eclipse. For a total or annular eclipse they equal the ground point. When the Moon&amp;#39;s shadow axis misses the Earth, as it does for every partial eclipse and a few non-central annular and total ones, they give the point on the Earth&amp;#39;s limb nearest the axis, where the Sun&amp;#39;s center is on the geometric horizon, and the fraction of the Sun covered there. &lt;code&gt;latitudeDeg&lt;/code&gt;, &lt;code&gt;longitudeDeg&lt;/code&gt;, and &lt;code&gt;obscuration&lt;/code&gt; keep their meaning and are still &lt;code&gt;null&lt;/code&gt; for a partial eclipse.&lt;/li&gt;
&lt;li&gt;Swift&amp;#39;s &lt;code&gt;GlobalSolarEclipse&lt;/code&gt; public initializer takes the three new values as required arguments, so code that constructs the struct by hand needs updating.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The point is checked against the Espenak Five Millennium Catalog for all 122 eclipses from 1950 through 2100 whose axis misses the Earth, 115 partial and 7 non-central:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst residual&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Point against the catalog&amp;#39;s whole-degree coordinates&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.63°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1°&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geometric Sun altitude there&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.0011°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.01°&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local search placed there: peak against greatest eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.95 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local search placed there: obscuration&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;about 1e-9&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1e-6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The local search placed at the point also reports the catalog&amp;#39;s kind for all 122. The performance comparison showed no regression in either port. Validation includes 178 TypeScript tests, 137 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.6.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.6.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Greatest eclipse for partial solar eclipses: #43, #44, #45.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.5.0...v0.6.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Solar eclipses anywhere on Earth, with central lines (Almanac 0.5.0)</title>
      <link>https://openwaters.io/updates/almanac-0-5-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-5-0/</guid>
      <pubDate>Sun, 27 Sep 2026 18:21:24 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.5.0 adds solar eclipses anywhere on Earth, and the central line of each total or annular eclipse, in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextGlobalSolarEclipse(after:)&lt;/code&gt; / &lt;code&gt;nextGlobalSolarEclipse(after)&lt;/code&gt;, &lt;code&gt;previousGlobalSolarEclipse(before:)&lt;/code&gt; / &lt;code&gt;previousGlobalSolarEclipse(before)&lt;/code&gt;, and &lt;code&gt;globalSolarEclipses(from:to:)&lt;/code&gt; / &lt;code&gt;globalSolarEclipses(from, to)&lt;/code&gt; find solar eclipses with no observer. Each result carries the time of greatest eclipse, the shadow axis&amp;#39;s distance from the Earth&amp;#39;s center, and where the axis meets the ground, with the kind (partial, annular, or total) and obscuration seen from there. When the axis misses the Earth, the eclipse is partial, with no ground point.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;solarEclipseAxisPoint(at:)&lt;/code&gt; / &lt;code&gt;solarEclipseAxisPoint(time)&lt;/code&gt; gives where the shadow axis meets the ground at any instant, or nothing when it misses.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;solarEclipseCentralLine(peak:stepSeconds:)&lt;/code&gt; / &lt;code&gt;solarEclipseCentralLine(peak, stepSeconds)&lt;/code&gt; traces the central line from where the axis first touches the Earth to where it leaves. Interior points fall on whole multiples of the step since the Unix epoch, which defaults to 60 seconds, so a line at a step that is a whole multiple of another samples a subset of its instants.&lt;/li&gt;
&lt;li&gt;The shared performance harness gains five global workloads. &lt;code&gt;benchmarks/run.mjs --skip &amp;#39;^global/&amp;#39;&lt;/code&gt; leaves them out when the comparison base predates 0.5.0.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The global search finds all 337 solar eclipses from 1950 through 2100 in the Espenak Five Millennium Catalog, with no extras, and every kind matches. The central line is checked against NASA&amp;#39;s path tables for six central eclipses, at the same dynamical time:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst residual&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Greatest eclipse, 337 eclipses&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8.2 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Axis distance against catalog gamma&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4.1 km&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5 km&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ground point, 202 eclipses with the axis under 6,100 km&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.66°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1°&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central line against NASA path tables&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3.1 km, 4.9 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5 km, 60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central line of the grazing 2044-08-23 eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;9.4 km, 8.1 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;15 km, 60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annular obscuration against the diameter ratio squared&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.0010&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local search at 953 central-line points: peak&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.40 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/actions/runs/36339002754&quot;&gt;hosted CI comparison&lt;/a&gt; measured these median query times, in milliseconds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;TypeScript&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Swift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Next global solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.22&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previous global solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.18&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global solar eclipses / 228 hours, no new moon&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.006&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.005&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global solar eclipses / 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;149&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;111&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Central line of 2024-04-08, 60 s step&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.3&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both revisions used the same harness and toolchain within each port, with seven interleaved process pairs and 300 ms warmup. No existing workload moved by more than 2.6% in either port. Validation includes 174 TypeScript tests, 133 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.5.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.5.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Global solar eclipses: #39, #40, #42. Development and toolchain: #36. Dependency updates: #37.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.4.2...v0.5.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Faster sunrise, sunset, and twilight searches (Almanac 0.4.2)</title>
      <link>https://openwaters.io/updates/almanac-0-4-2/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-4-2/</guid>
      <pubDate>Sun, 20 Sep 2026 04:53:21 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.4.2 speeds up Sun and Moon rise, set, and twilight searches in TypeScript and Swift, and the Sun&amp;#39;s position in TypeScript. The public API is unchanged.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Event searches find altitude extrema with Brent&amp;#39;s method instead of a fixed 22-sample golden section, and find altitude crossings with a cosine-seeded secant solver. Every crossing is still proven inside a half-second bracket, and anything that stalls or leaves the segment falls back to the bracketed search. Sampler calls for a year at Victoria drop from 40,681 to 15,400 for Sun events and from 24,437 to 10,173 for Moon events.&lt;/li&gt;
&lt;li&gt;The TypeScript Sun series evaluates its 51 VSOP87 terms as straight-line arithmetic rather than iterating the coefficient table, for bit-for-bit identical results. Swift already evaluated the series efficiently and mirrors the structure for the twin-port contract.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The focused year benchmark returns the same 3,255 Sun events:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.1&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.2&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;136.267 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;36.268 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;73.4% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;56.322 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;20.963 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;62.8% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Moon events over the same year are 57.6% faster in TypeScript and 57.4% faster in Swift. Sun positions, the sky track, Moon phases, and every lunar and solar eclipse workload are 21% to 36% faster in TypeScript; Swift&amp;#39;s remaining workloads are within 2%.&lt;/p&gt;
&lt;p&gt;Each search now reports the root inside its verified bracket rather than the bracket&amp;#39;s midpoint, so event times move by at most a third of a second. Across 1950 through 2100 at Victoria, 60°N, the equator, and 70.5°S, every event count, kind, and order is identical, and the parity corpus still holds 9,449 Sun events and 2,115 Moon events.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.4.2
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.4.2&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sun series: #32. Event searches: #34.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.4.1...v0.4.2&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Faster Moon positions and Moon events (Almanac 0.4.1)</title>
      <link>https://openwaters.io/updates/almanac-0-4-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-4-1/</guid>
      <pubDate>Tue, 15 Sep 2026 15:01:51 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.4.1 speeds up Moon positions and the searches built on them in TypeScript and Swift. The public API is unchanged.&lt;/p&gt;
&lt;p&gt;The focused year benchmark returns the same 705 Moon events:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.0&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;v0.4.1&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;127.918 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;53.918 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;57.8% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;127.762 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;42.581 ms&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;66.7% faster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Representative Moon-dependent workloads are 35% to 62% faster in TypeScript and 51% to 69% faster in Swift.&lt;/p&gt;
&lt;p&gt;This release also makes the tag workflow create a GitHub release for every published version.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.4.1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.4.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moon performance: #29. Release automation: #28.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.4.0...v0.4.1&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Positions of fixed stars (Almanac 0.3.0)</title>
      <link>https://openwaters.io/updates/almanac-0-3-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-3-0/</guid>
      <pubDate>Tue, 15 Sep 2026 14:58:48 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.3.0 adds the altitude and azimuth of any fixed star in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;starAltAz(raDeg:decDeg:at:observer:)&lt;/code&gt; / &lt;code&gt;starAltAz(raDeg, decDeg, time, observer)&lt;/code&gt; takes a star&amp;#39;s J2000 catalog right ascension and declination and returns its refracted topocentric altitude and azimuth. It precesses and nutates the position to date and uses the same sidereal time and refraction as &lt;code&gt;sunAltAz&lt;/code&gt; and &lt;code&gt;moonAltAz&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Annual aberration, proper motion, and stellar parallax are not applied. Aberration is at most 20.5″, and all but a few fast-moving stars shift by only arcseconds per decade.&lt;/li&gt;
&lt;li&gt;An out-of-range right ascension or declination is a validation error, like an invalid observer.&lt;/li&gt;
&lt;li&gt;The library ships no star catalog; callers pass the coordinates they already carry.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The star positions are checked against the USNO celestial-navigation almanac for the navigational stars at Victoria and at 35°S, on the 2026 equinoxes and solstices, 1999-01-17, and 2050-06-21, with J2000 positions from SIMBAD. The tests compare every star above 10° altitude and leave out the twelve stars whose proper motion would exceed the tolerance by 2050.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;right&quot;&gt;Positions checked&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst altitude error&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst azimuth error&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;197&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.45′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.51′&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Validation includes 88 TypeScript tests, 93 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.3.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.3.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Requested in #12. Changes: #13, #14.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.2.1...v0.3.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Offline Sun and Moon astronomy for TypeScript and Swift (Almanac 0.1.0)</title>
      <link>https://openwaters.io/updates/almanac-0-1-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-1-0/</guid>
      <pubDate>Tue, 15 Sep 2026 14:58:40 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.1.0 is the first release: offline Sun and Moon astronomy for TypeScript and Swift, with one behavior in both ports and no network access or runtime data files.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sunPosition&lt;/code&gt; and &lt;code&gt;moonPosition&lt;/code&gt; give geocentric apparent right ascension, declination, and distance. &lt;code&gt;sunAltAz&lt;/code&gt; and &lt;code&gt;moonAltAz&lt;/code&gt; give refracted topocentric altitude and azimuth.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sunEvents&lt;/code&gt; finds sunrise, sunset, civil, nautical, and astronomical twilight, and transit within a window. &lt;code&gt;moonEvents&lt;/code&gt; finds moonrise and moonset from the Moon&amp;#39;s upper limb.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;moonIllumination&lt;/code&gt; reports the illuminated fraction, phase angle, phase, and waxing state, and &lt;code&gt;searchMoonPhases&lt;/code&gt; finds new, first-quarter, full, and last-quarter moons.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nextLunarEclipse&lt;/code&gt; returns the kind, peak, magnitudes, and contact times of the next lunar eclipse, and &lt;code&gt;lunarEclipseVisibility&lt;/code&gt; reports which contacts an observer can see.&lt;/li&gt;
&lt;li&gt;Every function covers 1950 through 2100 and raises a typed out-of-range error outside that interval. The functions share names across both ports, with Swift argument labels. The algorithms are translated from Astronomy Engine by Don Cross.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both ports are tested against the same external fixtures and a cross-port parity corpus, with these tolerances:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sun and Moon position&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1′&lt;/td&gt;
&lt;td&gt;JPL Horizons, 1,839 samples each across 1950–2100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sun distance&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1e-4 AU&lt;/td&gt;
&lt;td&gt;JPL Horizons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moon distance&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;70 km&lt;/td&gt;
&lt;td&gt;JPL Horizons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rise, set, twilight, and phase times&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;td&gt;USNO rise and set grid, 693 USNO moon phases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar eclipse peaks and magnitudes&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s, 0.03&lt;/td&gt;
&lt;td&gt;All 344 eclipses in the Espenak catalog, 1950–2100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar eclipse contacts&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;td&gt;NASA contact tables for four eclipses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Event searches scale with window length: a full 151-year window takes about 68 s in TypeScript and 44 s in a Swift release build, so run long searches off the main thread. Validation includes 80 TypeScript tests, 84 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.1.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Changes: #1.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/commits/v0.1.0&quot;&gt;Full history&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Solar eclipses visible from a location (Almanac 0.4.0)</title>
      <link>https://openwaters.io/updates/almanac-0-4-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-4-0/</guid>
      <pubDate>Mon, 14 Sep 2026 18:39:11 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.4.0 adds solar eclipses for an observer in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextSolarEclipse(after:observer:)&lt;/code&gt; / &lt;code&gt;nextSolarEclipse(after, observer)&lt;/code&gt;, &lt;code&gt;previousSolarEclipse(before:observer:)&lt;/code&gt; / &lt;code&gt;previousSolarEclipse(before, observer)&lt;/code&gt;, and &lt;code&gt;solarEclipses(from:to:observer:)&lt;/code&gt; / &lt;code&gt;solarEclipses(from, to, observer)&lt;/code&gt; find the solar eclipses a place can see. Each result carries the kind (partial, annular, or total), the obscuration at peak, contacts C1 through C4, and the Sun&amp;#39;s altitude at each contact. C2 and C3 are present only for annular and total eclipses.&lt;/li&gt;
&lt;li&gt;An eclipse whose Sun is below the horizon at C1, the peak, and C4 is not returned. Next and previous searches walk to the edge of the supported interval, because a place can go years without a visible solar eclipse.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;solarObscuration(at:observer:)&lt;/code&gt; / &lt;code&gt;solarObscuration(time, observer)&lt;/code&gt; gives the fraction of the Sun&amp;#39;s disc the Moon covers at any instant, for drawing an eclipse as it happens.&lt;/li&gt;
&lt;li&gt;The shared performance harness gains seven solar workloads. &lt;code&gt;benchmarks/run.mjs --skip &amp;lt;regex&amp;gt;&lt;/code&gt; leaves them out when the comparison base predates 0.4.0.&lt;/li&gt;
&lt;li&gt;Swift CI runs on Linux with Swift 6.3.3, and the TypeScript package builds with TypeScript 7.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The searches are checked against USNO local circumstances for eight places and against all 337 solar eclipses from 1950 through 2100 in the Espenak Five Millennium Catalog. The worst residuals sit well inside the contract&amp;#39;s tolerances:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Worst residual&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tolerance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;USNO contacts C1 through C4&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7.2 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USNO peak&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7.0 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;300 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Catalog peak, 215 central eclipses&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;123 s&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;300 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USNO obscuration&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.001&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USNO Sun altitude at a contact&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.06°&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.5°&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/actions/runs/34825453137&quot;&gt;hosted CI comparison&lt;/a&gt; measured these median query times, in milliseconds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;TypeScript&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Swift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Next solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8.1&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;6.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previous solar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;6.9&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 228 hours, one visible&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.72&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 228 hours, new moon not visible&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.48&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 228 hours, no new moon&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.012&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;0.009&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solar eclipses / 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;391&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;295&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Obscuration / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.8&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both revisions used the same harness and toolchain within each port, with seven interleaved process pairs and 300 ms warmup. No existing workload moved by more than 2.1% in either port. Validation includes 127 TypeScript tests, 109 Swift release tests, and the shared fixture and parity checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.4.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.4.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Solar eclipses: #24, #27. Development and toolchain: #15, #22, #23, #25, #26. Dependency updates: #16, #17, #18, #19, #20, #21.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.3.0...v0.4.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Faster Moon, Sun, and eclipse calculations (Almanac 0.2.1)</title>
      <link>https://openwaters.io/updates/almanac-0-2-1/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-2-1/</guid>
      <pubDate>Mon, 07 Sep 2026 12:36:42 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.2.1 reduces repeated astronomy work in TypeScript and Swift, with the same public API and fixture tolerances.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reuse Moon geometry for illumination and flatten the Moon model&amp;#39;s scratch arrays.&lt;/li&gt;
&lt;li&gt;Share solar crossing probes, skip crossings before the requested window, and accelerate altitude refinement with a verified bracket and bisection fallback.&lt;/li&gt;
&lt;li&gt;Reuse peak shadow geometry when calculating eclipse contacts.&lt;/li&gt;
&lt;li&gt;Expand the shared performance harness to 15 workloads, including an empty eclipse window that exercises latitude pruning, and document how to reproduce comparisons in the README.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/openwatersio/almanac/actions/runs/34119038860&quot;&gt;hosted CI comparison&lt;/a&gt; measured these reductions in median query time versus the 0.2.0 astronomy code:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;TypeScript&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Swift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sky track / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;40.0%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;42.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sun events / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;39.3%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;40.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moon events / 228 hours&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;39.1%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;35.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previous lunar eclipse&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;26.0%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;36.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lunar eclipses / 1950–2100&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;26.4%&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;23.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both revisions used the same harness and toolchain within each port, with seven interleaved process pairs and 300 ms warmup. Build/startup time is excluded; timings vary by machine. All 15 workloads pass the 20% regression gate in both ports.&lt;/p&gt;
&lt;p&gt;Refined rise/set and twilight times can shift by up to 600 ms after quantization; event counts and kinds are unchanged, and existing accuracy and parity tolerances are preserved. Validation includes 86 TypeScript tests, 91 Swift release tests, and the shared fixture checks.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.2.1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.2.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Performance changes: #10.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.2.0...v0.2.1&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Search past lunar eclipses and date ranges (Almanac 0.2.0)</title>
      <link>https://openwaters.io/updates/almanac-0-2-0/</link>
      <guid isPermaLink="true">https://openwaters.io/updates/almanac-0-2-0/</guid>
      <pubDate>Mon, 07 Sep 2026 11:22:10 GMT</pubDate>
      <category>Release</category>
      <description>&lt;p&gt;Almanac 0.2.0 adds backward and range lunar eclipse searches in TypeScript and Swift.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;previousLunarEclipse(before:)&lt;/code&gt; / &lt;code&gt;previousLunarEclipse(before)&lt;/code&gt; finds the previous eclipse directly, retaining the 100 ms same-eclipse band used by next searches.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lunarEclipses(from:to:)&lt;/code&gt; / &lt;code&gt;lunarEclipses(from, to)&lt;/code&gt; returns eclipse peaks in a sorted, half-open &lt;code&gt;[from, to)&lt;/code&gt; window. Visibility remains a separate observer query.&lt;/li&gt;
&lt;li&gt;Stable peak calculations and Swift date normalization allow adjacent windows to split at a returned peak. The root solver also rejects narrow intervals without a crossing.&lt;/li&gt;
&lt;li&gt;A shared performance harness compares both ports against the base revision in CI, with macOS benchmarks gated on the cheaper TypeScript job.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compared with the previous consumer loops, CI measured previous searches about 86% faster and 228-hour range searches 65–99% faster. Stable boundary handling adds about 0.1 ms to next searches (8–11%); all workloads pass the 20% regression gate.&lt;/p&gt;
&lt;p&gt;Validated against all 344 catalog eclipses, with 86 TypeScript tests, 91 Swift tests, and unchanged fixture/parity tolerances.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm install @openwaters/almanac@0.2.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot;&gt;.package(url: &amp;quot;https://github.com/openwatersio/almanac.git&amp;quot;, exact: &amp;quot;0.2.0&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Changes: #7, #8.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openwatersio/almanac/compare/v0.1.0...v0.2.0&quot;&gt;Full changelog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
  </channel>
</rss>
