A Real Complication
How Solvane puts a working sky on a watch face
What's a watch complication? It is basically anything a watch does beyond telling you the time. The word is a description: every extra function complicates the movement. Calendars, moon phases, chimes, and near the top of the tree the astronomical ones. The equation of time, which shows how far the sun is running ahead of or behind the clock. Sunrise and sunset indicators. Perpetual calendars that know about leap years without being told.

Those were how watchmakers proved themselves when they had almost nothing to work with. Gears, a spring, a few cubic centimeters of space, no electricity. Everything the watch knew about the sky had to be encoded in the ratio between two wheels. A sunrise indicator was not a picture of a sunrise. It was a mechanism with the sky's behavior built in.

I have wanted to make a real complication for a long time: a working model of the sky rather than a decoration that refers to one. Solvane is my attempt, and the second project I am writing about from Time Flies Select, a small collection for pieces that are interesting as horology and not only as design.
7,346
Solvane. Interactive prototype of the watch face.
Besides the time
The upper half of the dial is the sky above your horizon, and it behaves like the one outside your window. In the afternoon it is deep and bright. An hour before sunset it warms along the bottom, on the side where the sun is actually going down. After sunset the color drains upward and the stars come out, turning slowly around the celestial pole, which sits higher or lower on the dial depending on how far north or south you are.
Sunrise, solar noon and sunset on the same day at 40° N
Crossing the dial is a thin arc: the path the sun takes today. The peak of the arc is solar noon. The two points where it meets the horizon are today's sunrise and sunset. The marker riding along it is the sun, a filled disc while it is up and an outlined ring once it has set. The whole day is in front of you at once, and a glance tells you how much of it is left.

That arc is rebuilt every day. Tomorrow's is a slightly different shape, a little taller or flatter, a little longer or shorter, because tomorrow the sun climbs to a different height and the day is a different length. Over a year the arc rises and falls, and the sky follows it.
One place, three dates. On June 21 the arc is tall and the day long, by December 21 both have collapsed.

You set your latitude once, choosing from twenty-five bands five degrees apart, each labeled with a few cities so you can find yourself without knowing your coordinates. That single setting changes the rest: how steep the arc is, how quickly the sun crosses the horizon, how high the stars turn. At the same moment on the same date, a dial set to 60° N and a dial set to the equator show different skies, and both are right.
The same instant at 60° N and on the equator
The rest of the watch face is, well, a watch. Hands, date, minute and hour marks, complications, six color presets. The sky sits behind all of it and never competes with the time.
The six presets. The sky and the track stay as they are, everything drawn over them changes.
A format with no code
Wear OS watch faces are now built in Watch Face Format, which is declarative XML. No loops, no functions you can define, no state carried from one frame to the next. What you get is a tree of drawing elements and a small expression language, arithmetic and trigonometry and a conditional, which can be attached to almost any attribute of almost any element.

Gears were an awful way to express astronomy and watchmakers did it anyway. Everything below happens inside a constraint of the same kind.

The first useful step was realizing I did not need the sun's altitude, only the sine of it.

The usual way to state where the sun is involves an angle above the horizon, and pulling that angle out costs an inverse trigonometric function. Almost nothing in the design wants the angle; it wants how high the sun is, on a scale from below to above. That comes out of three inputs using nothing but multiplication and cosine:
sin(altitude) = sin(latitude) × sin(declination) + cos(latitude) × cos(declination) × cos(hour angle)
Both directions, the up where you stand and the line to the sun, point out of the center of the earth, and the cosine of the angle between them is what you get by multiplying them together coordinate by coordinate. Latitude tilts the first away from the equator, declination tilts the second, and the hour angle is how far the earth has turned them apart: fifteen degrees per hour, zero at solar noon.

Declination has a friendlier meaning than its name suggests. It is the latitude where the sun stands directly overhead today: the Tropic of Cancer in late June, when declination is 23.44 degrees north, the Tropic of Capricorn in late December, the equator at the equinoxes. It moves because the earth's axis is tilted and keeps pointing the same way all year, so half the year leans one hemisphere toward the sun and half leans it away.

Seen from the ground, the sun's yearly path is a circle inclined to the celestial equator, and its height above that equator depends on two things only: how far round the circle it has traveled since the March equinox, and how steeply the circle is tilted. Both arrive as sines, so declination never has to become an angle either:
sin(declination) = sin(earth's tilt) × sin(distance traveled round the circle)
cos(declination) = √(1 − sin(declination)²)
What the formula is asking, and where declination comes from
The tidy alternative is an arcsine feeding straight back into sines and cosines, two expensive operations to arrive where you started. The second line is Pythagoras doing the work of an inverse function instead. That is the shape of most of the arithmetic in this project: work out which trigonometric quantity you actually need, and avoid turning it into an angle on the way.

This single number then drives the rest of the dial. The vertical position of the sun marker is a straight scaling of it. The opacity of the daylight layer is that number crossing a threshold. The twilight layer is a peak centered just below zero. Stars fade in once it goes far enough negative. The halos grow and brighten with it, and the disc warms and cools with it. One value, computed once per frame, with dozens of consumers hanging off it.
The sky is four layers, and each one is an opacity computed from the sun's height
Drawing a curve when there is no curve
The format can draw rectangles, ellipses, arcs, lines and images. It cannot draw an arbitrary path. And the sun's daily track is not an arc of a circle: it is a cosine, flattened or stretched by your latitude and the season.

It helps that the formula above is already a wave, once it is grouped properly. Only the last factor depends on the time of day:
sin(altitude) = A + B × cos(hour angle)
A = sin(latitude) × sin(declination)
B = cos(latitude) × cos(declination)
A is where the middle of the day's swing sits, B is how far it swings, and both are fixed for a given date and place. So the sun's whole day is one cosine wave, raised by A and stretched by B. In midsummer at a high latitude the wave barely dips below the horizon; in midwinter it is the other way round.

The same two numbers give the length of the day, with no extra machinery. Sunrise and sunset are where the wave crosses the horizon:
cos(half the day, in hour angle) = (sin(horizon) − A) / B
If that comes out beyond plus or minus one the wave never crosses at all, and you have a polar day or a polar night. The dial handles both without a special case.

The horizon in that expression is not zero. The sun counts as risen when its center is 0.833 degrees below the geometric horizon, because the atmosphere bends its light up over the edge and because the disc has a visible radius. The sine of that angle, −0.0145, is the number that sits in the file.

So the track is fifty straight lines laid end to end, and the vertical coordinate of every endpoint comes from that expression. Fifty short chords read as a smooth curve at this size.

It came out speckled: faint bright dots at regular intervals along the track. My first guess was rounding. The cause was that the transparency lived in the line's color and the ends of the segments were rounded, so at every joint two semi-transparent caps overlapped and added up. Fifty joints, fifty bright dots.
The speckled track and the fixed one, magnified
The fix was to move the transparency off the color and onto the layer, so the track is drawn at full strength and faded once, and to square off the ends so segments butt against each other.
Light
The sun itself is 16 pixels across, and almost all of the work around it is light.
Every layer of that light is the same number put through a small piece of arithmetic. Twilight, for instance, is a peak function centered just below the horizon rather than a state the dial switches into:
twilight opacity = clamp(1 − |sin(altitude) + 0.05| / 0.18, 0, 1)
Brightest when the sun is a little way under, falling off in both directions, gone by the time it is properly up or properly down. The daylight layer is a ramp on the same number, the stars are a ramp on its negative, the halos scale with it.

While the sun is above the horizon the marker is a filled disc, and its color is not fixed. Low in the sky it is a warm ochre, and as it climbs it whitens, which is roughly what happens to sunlight when it has less atmosphere to travel through. Once it sets, the disc becomes an outlined ring.
The marker high, setting, and below the horizon
Around it are two halos, a warm one close in and a cool one further out. Both grow with the sun's height, and both fade out completely at the horizon, because a glow hanging around a sun that has already set looks wrong.

The first version had a visible seam where the bright core met the diffuse part, especially on an OLED screen in a dark room. I had built the halos from three and four gradient stops, which is how you would sketch a glow; on a real screen that is a bright disc with a ring around it.
Three gradient stops against nine
The version that works has nine stops in each halo, and the part that matters is that the color changes along all of them, not only the transparency.
The finished model, one cosine wave drawn as fifty straight segments
It worked, but it was wrong
By this point the dial was doing everything it was supposed to. Then I started comparing sunset on the watch against sunset in the world, and they did not agree. In some places by close to an hour. From the very beginning I did not plan this watch face to be an astronomically precise tool, but rather a nice-looking companion to your day, showing the sun's position beautifully. But at this point the average error was a bit too big.

The cause was politics rather than astronomy. A time zone is a legal object, drawn around borders and convenience, and it can be enormous. My model was deriving your position on the globe from your time zone's offset, which is a reasonable first approximation and quietly wrong across a lot of the world.

Iceland is the clearest case: Reykjavik keeps UTC while sitting almost twenty-two degrees west of the Greenwich meridian, so a longitude taken from the offset is out by an hour and a half. Spain runs on Central European Time from roughly the British meridian, and the western edge of China is more than three thousand kilometers from Beijing on Beijing time. It is not only the famous cases either: the earth turns four minutes of time for every degree of longitude, so an ordinary city five degrees west of its zone's nominal meridian has a sun that runs twenty minutes late.

The fix came with a constraint. I did not want to solve this by adding a setting, because choosing your latitude is already about as much as I am willing to ask of someone who just wants a good looking watch face.

What the watch does know, without being asked, is the name of its time zone. Not the offset, the name. So the dial carries a table of two hundred zone names together with the real longitude of the place each one is named after, and for the handful of zones wide enough that a single longitude will not do, it narrows the answer using the latitude you already chose. An unknown zone falls back to the old behavior, so nothing can break.

Then I replaced the short approximations for the sun's declination and for the equation of time with the proper series. Across fourteen cities on every continent, averaged over twelve dates through the year and checked against the NOAA algorithm, the average error in sunset fell from twenty-seven minutes to three. Reykjavik, the worst case, went from ninety minutes to nine.
Average sunset error across fourteen cities, before and after
The person wearing the watch does nothing. That was the point.
Solar noon
The next correction started with how the face looked: on the watch, the peak of the arc seemed to sit slightly to the right of center. It looked like a drawing mistake, and it was a real offset with a real cause.

The horizontal axis of the dial was carrying clock time: midnight at one edge, midnight at the other, twelve o'clock in the middle. But solar noon, the moment the sun is genuinely highest, almost never falls at twelve. It drifts with your position inside your time zone, with daylight saving, and with the equation of time, the small yearly wobble that comes from the earth's orbit being an ellipse and its axis being tilted, which on its own swings between about minus fourteen and plus sixteen minutes. For example, in St Petersburg on August 21 solar noon lands at 12:57, and that was exactly the fourteen pixels I had been looking at.

So I rebuilt the axis to carry solar time. The hour angle becomes fifteen degrees times the solar hour, minus a hundred and eighty: zero at the peak, by definition. The peak now sits dead center by construction, sunrise and sunset are symmetric around it, and the shape you see is the shape of your day. The reading shifts slightly with it: the sun in the middle of the dial means solar noon, not twelve o'clock.
The same moment with the axis on clock time and on solar time
There was an engineering dividend I had not expected. Once the axis carries solar time, each point along the curve sits at a fixed hour angle, so the trigonometry that gives the curve its shape can be worked out when the file is built rather than while the watch is drawing. All fifty segments lost their runtime trigonometry, and the curve became cheaper and more correct at the same time.
When the screen goes to sleep
Smartwatches spend most of the day in always-on mode, showing a dimmed dial without waking properly. There is a strict cap on the share of pixels allowed to be lit, around fifteen percent, which for a face built on a glowing sky is an interesting problem.

Solvane handles it by taking the sky away and keeping the mechanism. The gradient, the stars, the glow and the halos fade out over about a second, and what remains is the track, the sun riding on it, the marks and the hands. At the same moment the six long hour marks slide outward from the center, and the hour numerals fade in behind them, filling the space the marks have just left. It reads as one movement rather than three things happening at once, which took some care with the timing, because the format lets every layer start at its own point inside the transition and finish at its own pace.
Active, mid transition, always on
You raise your wrist and the sky arrives.
How close it gets
This is worth mentioning, because the rest of the article is about getting the model right. Solvane is not an astronomical almanac. It will not give you sunrise to the minute.

The format gives a watch face no access to your location, so the dial works from the two things it can have: the latitude band you chose, in five degree steps, and the name of your time zone. Two approximations follow. Your latitude is rounded to the nearest band, which for a city sitting midway between two bands is the largest error left in the model. Your longitude is the longitude of the city your zone is named after, not yours. On top of that the horizon is the standard one, 0.833 degrees below level, which assumes flat ground and average air. A hill to the west, or an unusually cold morning, will move real sunset further than the model's own error does.

In practice that comes out within a few minutes for most places, and at worst around a quarter of an hour near the edge of a band. Close enough that the dial changes when the sky outside changes, and too coarse for anything that needs the exact minute.

So the sun on Solvane is a companion. If you want sunrise and sunset to the minute, put a complication on the dial that fetches them; there is a slot for it and the two sit together well. What the dial itself gives you is the shape of the whole day, drawn correctly for where and when you are, a little different every day of the year.
A promise
A complication is a promise. It says the watch knows something true about the world.

Solvane knows the date, the time, the name of its time zone and the band of latitude you picked. From those four things it works out where the sun is, and the sky follows. When it tells you the sun is about to set, it is, give or take those few minutes.

What surprised me is how much room there turned out to be inside the format. Watch Face Format looks, on first reading, like a way to arrange images on a dial. And yet it will evaluate a real astronomical model as it draws, build a curve out of fifty transformed line segments, run a color ramp through nine gradient stops, and stage a transition in which three layers move on three different schedules. All of it is in the format.

Old complications were proof that a watchmaker understood both the sky and the metal. That combination has not gone anywhere. The metal is just XML now 😃

Solvane is available here on Google Play. It belongs to Time Flies Select, a collection I am putting together for the projects that are interesting as horology and not only as design.
Put a working sky on your watch face
Solvane
Premium collection
A true caller GMT for Wear OS, with 28 selectable time zones
Meridan
Premium collection