Library / SDK
ceeK/Solar avatar
ceeK/Solar

Solar: sunrise and sunset times computed on device in Swift

A Swift micro library for generating Sunrise and Sunset times on device, requiring no network access.

615 stars87 forksSwiftMIT

At a glance

What is it?
Solar is a Swift package that calculates sunrise and sunset locally using an algorithm from the United States Naval Observatory, so an app can show day and night boundaries without a network call. Its API returns optionals and all dates in UTC.
Who is it for?
Solar suits an iOS, macOS, tvOS or watchOS app that needs sunrise and sunset or twilight times for a place and a date without depending on a service being reachable. It does not suit an application that needs the official sunrise and sunset for a specific official body, since the library describes its source as an algorithm rather than a published almanac, and it does not fit code that cannot deal with an optional result.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 52 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A day and night boundary without a network call

Solar is described as a Swift micro library for generating sunrise and sunset times, requiring no network access. That single constraint is the design decision everything else follows from.

Sunrise and sunset are the kind of data an app needs in places where the network is unreliable, expensive or absent. A fitness app that schedules outdoor sessions, a garden planner, a photography tool, a sleep tracker, a marine chart viewer or a watch face that shows daylight hours all need the same two timestamps for a coordinate, and all of them would otherwise call a service, cache the answer, and handle the case where the service does not answer.

Solar performs its calculations locally using an algorithm from the United States Naval Observatory. The library therefore has no server component, no API key, no rate limit and no failure mode that comes from someone else's uptime. The repository carries a Swift Package Manager compatibility badge, a CI badge, and separate Swift version and platform compatibility badges, and the topic tags place it on iOS, macOS, tvOS and watchOS.

The API takes a date and a coordinate, and hands back optionals

Usage is two lines of construction and two lines of reading. Solar simply needs a date and a location specified as a latitude and longitude.

swift
let solar = Solar(for: someDate, coordinate: CLLocationCoordinate2D(latitude: 51.528308, longitude: -0.1340267))
let sunrise = solar?.sunrise
let sunset = solar?.sunset

The date is optional too, and when you leave it out you get the sunrise and sunset for the current date and time.

swift
let solar = Solar(coordinate: CLLocationCoordinate2D(latitude: 51.528308, longitude: -0.1340267))
let sunrise = solar?.sunrise
let sunset = solar?.sunset

Notice the shape of the API. The initializer returns an optional Solar, the sunrise and sunset properties are optional, and every access in the examples is written with optional chaining. That means the type system makes you handle the case where a value is not produced, rather than handing you a value that might be meaningless. Whether that case is a polar day, a polar night or simply a coordinate outside the range the algorithm covers is not something the README spells out, so the safe assumption is that a nil has to be handled as a real outcome in your interface.

Four different definitions of the same event

This is the part of the API that surprises people, and the README gives the definition plainly. There are several types of sunrise and sunset that Solar generates, and they differ by how many degrees the sun lies below the horizon.

Official is about 0 degrees, meaning the moment the sun's upper limb crosses the horizon in the official sense used by the almanac. Civil twilight is 6 degrees below the horizon, the point at which ordinary outdoor activity is no longer practical without artificial light. Nautical is 12 degrees below, where the horizon is still visible at sea but navigation by celestial fix is no longer practical. Astronomical is 18 degrees below, where the sky is dark enough that stars are visible.

For most apps, civil twilight is the number that matches what users mean by it is getting dark. The trap is that the word sunset in a product spec often means one of these four, and the difference between official and civil is more than an hour at mid latitudes in summer. The README links to an explanation of the different types of twilight for background, but the choice is yours to make in code.

Every date comes back in UTC

There is a note in the README that deserves to be read twice: all dates are UTC, and you need to format your date into the appropriate timezone if required.

This is the right default for a library. Computing sunrise and sunset is inherently a geometry problem on the UTC timeline, and returning UTC removes the ambiguity of which timezone the answer is expressed in. The cost moves to the caller. A user in a different timezone from the coordinate still sees the sunrise time expressed in their own timezone, which may be a different day entirely from the sunrise at that location.

That is the detail most integrations get wrong. If your app shows a sunrise time to someone who is not in the same timezone as the coordinate, the correct behaviour is to format the returned UTC date in the coordinate's timezone if you want the local sunrise at that place, and in the user's timezone if you want it to read as their morning. The library gives you the instant and leaves that choice to you, and the README does not offer a timezone parameter to do it for you.

isDaytime and isNighttime wrap the two timestamps

The convenience methods cover the common case where you do not care about the exact minute of dawn, only whether it is light out.

swift
// Whether the location specified by the `latitude` and `longitude` is in daytime on `date`
let isDaytime = solar.isDaytime

// Whether the location specified by the `latitude` and `longitude` is in nighttime on `date`
let isNighttime = solar.isNighttime

This is a smaller library than most of its size suggests, and the convenience methods are the reason. An app that shows a themed icon, a screen tint or a notification window usually only needs a boolean, and computing it from the sunrise and sunset you already have is trivial. The trade is that the convenience properties do not take a twilight type, so they inherit whichever definition the library applies, and the README does not document an option to change it.

Installation through Swift Package Manager or Xcode

Solar is available through the Swift Package Manager, and the package dependency is declared in the dependencies value of your Package.swift.

swift
dependencies: [
    .package(url: "https://github.com/ceeK/Solar.git", .upToNextMajor(from: "4.0.0"))
]

The version requirement asks for any 4.x release, which is the usual SwiftPM convention of staying on a major version while taking patches and minors.

If you are working inside Xcode instead, the path is the menu item File, then Add Package Dependencies, and you enter the same repository URL, `https://github.com/ceeK/Solar.git`, as the package URL.

The repository itself is small and conventional: a Package.swift, a Solar/ source directory, a SolarTests/ directory, a Solar.xcodeproj/, the LICENSE file and the CI workflow under .github/. There is no service to deploy and no configuration file, so adoption is a package reference and an import.

Version 4 arrived with a same day patch release

The release history shows 3.0.1 from 2021-07-16, then 4.0.0 and 4.0.1 both dated 2026-08-30, with the last push on 2026-08-31. So the project sat on the 3.x line for years and then moved to 4.0.0, followed by a patch release on the same day and a commit the next day.

That pattern suggests a major version bump rather than a steady stream of minor work, and it means the .upToNextMajor(from: "4.0.0") requirement in the README is meaningful: you are pinning to a line that is one day old, not to a mature branch with a long history of fixes. The 3.x to 4.0.0 jump is a major version, so API changes are likely in that boundary, and if you have an existing integration on 3.0.1 you should expect to read the differences before moving.

The licence is MIT, with the terms in the LICENSE file at the repository root, and the README states that Solar is available under the MIT license. That is the simplest commercial position of the libraries here, and it applies to a package you vendor into a shipping application without the copyleft obligations of a weaker or file level licence.

Editorial conclusion

Solar suits an iOS, macOS, tvOS or watchOS app that needs sunrise and sunset or twilight times for a place and a date without depending on a service being reachable. It does not suit an application that needs the official sunrise and sunset for a specific official body, since the library describes its source as an algorithm rather than a published almanac, and it does not fit code that cannot deal with an optional result. Verify first which twilight type your product needs, since the four definitions differ by degrees below the horizon, and confirm that you handle the optional sunrise and sunset properties as the API returns them.

Frequently asked questions

How do I add the Solar Swift package to my project?

Add it to the dependencies value of your Package.swift with .package(url: "https://github.com/ceeK/Solar.git", .upToNextMajor(from: "4.0.0")). In Xcode you can use File, Add Package Dependencies and enter the same repository URL.

Does Solar need internet access to calculate sunrise and sunset?

No. It is described as a micro library requiring no network access, and it performs its calculations locally using an algorithm from the United States Naval Observatory.

What timezone are the sunrise and sunset dates returned in?

All dates are UTC. The README notes that you should format your date into the appropriate timezone if required.

What is the difference between the types of sunrise and sunset in Solar?

They differ by how many degrees the sun lies below the horizon: Official at about 0 degrees, Civil at 6 degrees, Nautical at 12 degrees and Astronomical at 18 degrees.

Official sources

  1. ceeK/Solar on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ceek-solar.svg)](https://hysenlabs.com/projects/ceek-solar)

Was this useful?