Dark Hours, Done Right: Modeling Sky Darkness and Building With Provenance
The moment “dark hours” became a real engineering problem
The first time you hear about dark hours, it sounds poetic. A few hours where the sky looks like it has depth. A time window where the Milky Way stops being an idea and becomes a texture.
Then you try to build it.
“How do we turn ‘dark enough for stars’ into something a computer can predict?” That question is where Dark Hours-style tools stop being a cute weekend project and start behaving like a forecasting engine: you need geometry (the Sun and Moon), physics-ish approximations (how light scatters through haze), and weather data (clouds, seeing, transparency). (darkhours.app)
And there’s an uncomfortable companion lesson: when you generate a project with AI, similarity to an existing open-source app can show up not as vibes, but as shared structure, matching feature lists, and even the same bugs.
This post is a technical walk-through of what it takes to build a night-sky planner, plus a practical provenance checklist so you don’t repeat that kind of “oops.”
Define the target: what counts as “dark”?
A helpful starting definition is astronomical twilight: the Sun is sufficiently far below the horizon that true night conditions begin. A common boundary is when the center of the Sun reaches 18° below the horizon. (dictionary.cambridge.org)
That doesn’t mean your sky will be perfect. It means the geometry of daylight is gone.
From there, you layer darkness from multiple angles:
- Sky darkness (light pollution) using something like Bortle class, a 1–9 scale describing how dark the naked-eye sky looks under light pollution. (en.wikipedia.org)
- Moonlight: even if it’s technically night, a bright Moon can wash out faint targets. Many tools treat the Moon as “up or down,” but a better approach models its extra sky glow (often described as “moonwash”). ()
- Atmosphere + weather: clouds are the obvious failure mode, but for astrophotography you also care about:
- Astronomical seeing (how much the atmosphere blurs the image)
- Atmospheric transparency (how much the air absorbs/scatters light)
For example, 7Timer’s ASTRO product explicitly includes astronomical seeing and atmospheric transparency in its forecast outputs. (7timer.info)
The scoring model: don’t hide a dealbreaker
Once you have inputs (moon brightness, sky brightness, cloud cover, wind stability, etc.), the hardest part is turning them into a single “night quality” number.
A trap is using a plain arithmetic average, because one catastrophic problem can be masked by several “good enough” factors. DarkHours specifically calls this out, using a geometric mean rather than an average so one bad factor drags the score down. ()
Geometric mean, in plain language
The geometric mean of values (x_1\dots x_n) is:
[
(\prod_{i=1}^n x_i)^{1/n}
]
If any factor is near zero (say, clouds), the product collapses and the overall score reflects the reality. With a normal average, a near-zero factor can be “diluted.”
A practical implementation pattern looks like this:
For each time slot:
score_components = [darkness, moon_factor, cloud_factor, seeing_factor, wind_factor]
normalized_components = map each component to a 0..1 range
night_quality = (product(normalized_components))^(1/n)
Return window with highest night_quality
The key is the normalization step: it must convert each metric into a comparable 0–1 “quality” scale, otherwise geometric mean becomes mathematically correct but conceptually meaningless.
Moonlight modeling: from “binary” to “how much glow”
The Moon isn’t an on/off switch. When you photograph under a crescent, contrast is different than under a gibbous.
A moonlight model typically needs:
- The Moon’s apparent position (or at least whether it’s near the target direction)
- A brightness model for lunar illumination
- A scattering model to estimate how that light bounces around the atmosphere through haze/smoke/aerosols
DarkHours describes using the Krisciunas & Schaefer (1991) model for lunar brightness combined with a more recent single-scatter approach (Winkler 2022) for forward-scattering through haze and smoke. (darkhours.app)
In engineering terms, you’re estimating the added sky background at the target, not just whether the Moon is “up.” That difference matters because astrophotography is a contrast game.
The weather pipeline: don’t treat weather as one number
Clouds are one variable, but astrophotography cares about more continuous effects.
A robust architecture usually looks like:
- Geocode your observation point (coordinates)
- Request forecast data (cloud cover + hourly profiles)
- Request astro layers: seeing and transparency (astronomy-focused products)
- Map these into your scoring factors
7Timer’s ASTRO product, for instance, defines seeing categories and transparency ranges, and it’s explicitly meant for astronomical forecasting rather than generic meteorology. (7timer.info)
Even if you don’t use exactly the same sources, the principle is the same: model the night as a timeline of conditions, not a single “weather summary.”
From predictions to “windows”: geometry + timeline simulation
Once you can score each time slice, the next user-facing feature is: when is the good part?
That’s where geometry shows up everywhere:
- compute twilight boundaries (sun altitude thresholds)
- compute target visibility (altitude / azimuth over time)
- compute the Moon’s relative brightness and direction as the night progresses
- account for horizon effects (light domes / horizon glow)
DarkHours highlights “Target Windows” and “Sky & Horizon Glow” as first-class concepts, including the idea of light domes around your horizon rather than relying only on Bortle class. ()
Implementationally, this is often a loop:
- for each minute (or 5-minute step):
- update solar state (twilight)
- update lunar state (phase + brightness estimate)
- update weather state (cloud/seeing/transparency)
- score
- then extract contiguous high-score segments and rank them
It feels computationally heavy, but it’s straightforward once your data model is consistent.
Open data and the “no-surprises” build process
Night-sky tools are data-driven, so the difference between “impressive demo” and “trusted planner” is sourcing and timestamps.
DarkHours describes integrating multiple datasets (light pollution, weather, aerosols/haze, aurora, satellites, ephemerides) and publishing under an MIT License while remaining open-source and free. ()
That ethos matters technically too: open components can be audited, tested, and swapped.
And that brings us to the mea culpa engineering lesson.
The provenance checklist: how AI projects can accidentally converge
The story behind Mea Culpa – Dark Hours is a reminder that “generated” doesn’t mean “original.” It can mean “unreviewed.” (blog.terrygodier.com)
In practice, similarity can creep in through:
- matching architecture patterns (same routes, same data shapes)
- matching bug signatures (a copied logic branch, an off-by-one in a time window)
- matching feature sets and naming choices
A practical way to prevent that
Before you build anything public, run a quick provenance pass:
- Search the idea space by feature, not name
- “moonlight modeling”, “geometric mean night quality”, “dark sky finder”, “astronomical twilight scoring” - Search the code space by technique
- if a model uses a known paper (e.g., Krisciunas & Schaefer), search that pattern too - Diff by behavior with minimal tests
- feed the same coordinates and timestamp into your prototype and compare outputs - Check licenses early
- even if code isn’t copied intentionally, dependencies and data terms can still matter
The goal isn’t paranoia. It’s making sure “I didn’t know” doesn’t become “and now we shipped it.”
Conclusion: prediction engines for the night sky need both math and humility
Building a Dark Hours-style tool is a multi-layer stack: solar geometry for twilight, light pollution and Bortle class for baseline darkness, moonlight modeling for contrast loss, and astro-aware weather inputs for seeing and transparency. ()
It’s also a reminder that open-source ecosystems are interconnected. When AI accelerates scaffolding, it can also accelerate convergence. Provenance checks, behavioral tests, and licensing hygiene are what keep “fast” from becoming “careless.” ()
When both pieces work—the physics-ish models and the ethical engineering habits—night planning turns from guesswork into a schedule you can trust.
Comments (0)
No comments yet. Be the first to respond!
Leave a Comment
Your comment will be visible after review.