Triple Faults for Debug

SunCalc 14.1: The Whole Day of the Sun on One Ring

Harald Hoyer October 22, 2026 #garmin #connectiq #monkeyc #gps

Ten years after its first release, my Garmin widget SunCalc got its first big update since 2021: a 24-hour twilight ring as the front page, a glance, settings, seven languages and support for 147 watches, from the fēnix 3 to the fēnix 9.

DISCLAIMER: This article and most of the code was written with AI agents. Use at your own risk.

SunCalc: sunrise, sunset, twilight, blue hour and golden hour on a Garmin watch

What SunCalc is

SunCalc shows the sun’s day for your position: sunrise and sunset, civil, nautical and astronomical twilight, the blue hour, the golden hour and solar noon. Photographers use it for the light, runners and hikers to know how long they can stay out. It needs only a GPS fix: no phone connection, no account, no network. It is free and open source at github.com/haraldh/SunCalc.

Until now, SunCalc was a list: press Start, then page through fifteen periods of the day one by one. The most common wish in the reviews and the forum thread was the obvious one: show me sunrise and sunset on one screen. It took a while.

The ring

SunCalc front page: 24-hour ring on a fēnix 9 Pro The ring for tomorrow, with the date as heading

The front page is a 24-hour clock in the style of Garmin’s own widgets, with noon at the top and midnight at the bottom. The ring is coloured by how high the sun is: deep blue for the night and astronomical twilight, lighter blue for nautical and civil twilight, red-orange for the blue-hour glow, gold around sunrise and sunset, pale gold for the golden hour into full daylight. A red arc marks the current time, ticks mark solar noon and solar midnight.

Inside the ring are two rows of times, morning on the left and evening on the right. By default that is sunrise/sunset and civil twilight; in Garmin Connect you can pick any of sunrise/sunset, civil, nautical or astronomical twilight, blue hour or golden hour for each row.

Up and Down step through the days. The heading changes from TODAY to the date, and the whole ring is recomputed for that day: handy when you plan tomorrow’s sunrise shoot tonight.

Every phase, and the glance

Details list: golden hour with start and end time SunCalc glance: countdown to sunrise and a twilight bar

Tap the ring or press Start, and the old list is still there: every period of the day with its start and end time, starting with the current one. Periods you never need can be hidden with Menu, as before.

On Connect IQ 4 watches (fēnix 7 and newer, current Forerunner, Venu, Instinct and so on) SunCalc runs as a super app with a glance in the widget carousel: a countdown to the next sunrise or sunset (or whatever event you choose), a twilight bar and the day’s times. The glance never switches on GPS itself; it uses the watch’s last known position, and falls back to the position SunCalc saved the last time it got a fix.

147 watches, one layout in code

SunCalc on an Instinct 2: band widths instead of colours, sun and date in the subscreen SunCalc on the original epix: the text fits inside the ring

The old SunCalc had per-device layout and resource files and supported about 90 devices. The new one draws everything in code, relative to the screen, and the device list, the launcher icons and the jungle file are generated from the installed SDK device library. Adding the fēnix 9, MARQ 3, Enduro 4 and Approach S72 was one script run.

“Relative to the screen” turned out to have a few special cases:

Float precision, or why all evening events happened at 19:00

Two old GitHub issues reported odd results: sunrise five hours late in Iceland, and sunset, dusk, nautical and astronomical dusk all at exactly the same minute. I could reproduce both with the same bug.

The algorithm (a port of suncalc.js) works with Julian dates, which are around 2,460,000 today. If the position arrives as a Float instead of a Double, Monkey C computes everything in single precision, and a 32-bit float near 2.46 million can only step in quarter days. Every event got rounded to the same 6-hour grid. SunCalc’s own code passed Doubles, but people using it as a library passed Floats, and the new saved-position fallback stores the position as float properties. Now calculate() widens its input to Double itself, and builds its Moments from integers, because the simulator otherwise keeps a float inside.

How it was tested

The unit tests check every event against reference times from sunrise-sunset.org for places that stress the edge cases: Hammerfest in polar night and under the midnight sun, McMurdo in the antarctic winter, Iceland, Quito on the equator, Ushuaia and Munich at the solstices and the equinox. Missing events (the sun never sets, or never reaches -18°) must come out as “no time”, not as a crash, as it once did.

GitHub Actions runs those tests in the Connect IQ simulator on one device per special case: the 1.2-era epix, a semi-round Forerunner 235, the 1-bit Instinct 2, my own MARQ Adventurer and a current AMOLED fēnix 8 Pro. The simulator likes to hang right after switching devices, so every device gets 90 seconds and one retry in a fresh simulator. Releases are cut by release-please from conventional commits.

Get it

Free, open source, without ads and without tracking. If something looks wrong on your watch, please open an issue. Four of the issues closed with this release had waited far too long for an answer; I’ll try to be quicker.