{"id":15779671,"url":"https://github.com/aldaviva/solcalc","last_synced_at":"2025-05-07T03:26:42.241Z","repository":{"id":235354558,"uuid":"790503947","full_name":"Aldaviva/SolCalc","owner":"Aldaviva","description":"☀ Find when sunrise, sunset, and different twilights happen for a given location, based on the NOAA ESRL Solar Calculator.","archived":false,"fork":false,"pushed_at":"2025-03-25T03:04:56.000Z","size":1243,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-06T19:09:32.619Z","etag":null,"topics":["day","night","solar","solar-time","sun","sunrise","sunset","time","twilight"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/SolCalc/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Aldaviva.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://paypal.me/aldaviva"]}},"created_at":"2024-04-23T02:07:03.000Z","updated_at":"2025-03-25T03:04:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"66723946-956d-4886-b0b0-66159cedc3cb","html_url":"https://github.com/Aldaviva/SolCalc","commit_stats":null,"previous_names":["aldaviva/solcalc"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aldaviva%2FSolCalc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aldaviva%2FSolCalc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aldaviva%2FSolCalc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aldaviva%2FSolCalc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Aldaviva","download_url":"https://codeload.github.com/Aldaviva/SolCalc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252805730,"owners_count":21807064,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["day","night","solar","solar-time","sun","sunrise","sunset","time","twilight"],"created_at":"2024-10-04T18:20:57.017Z","updated_at":"2025-05-07T03:26:42.201Z","avatar_url":"https://github.com/Aldaviva.png","language":"C#","funding_links":["https://paypal.me/aldaviva"],"categories":[],"sub_categories":[],"readme":"☀ SolCalc\n===\n\n[![NuGet](https://img.shields.io/nuget/v/SolCalc?logo=nuget)](https://www.nuget.org/packages/SolCalc) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Aldaviva/SolCalc/dotnetpackage.yml?branch=master\u0026logo=github)](https://github.com/Aldaviva/SolCalc/actions/workflows/dotnetpackage.yml) [![Testspace](https://img.shields.io/testspace/tests/Aldaviva/Aldaviva:SolCalc/master?passed_label=passing\u0026failed_label=failing\u0026logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA4NTkgODYxIj48cGF0aCBkPSJtNTk4IDUxMy05NCA5NCAyOCAyNyA5NC05NC0yOC0yN3pNMzA2IDIyNmwtOTQgOTQgMjggMjggOTQtOTQtMjgtMjh6bS00NiAyODctMjcgMjcgOTQgOTQgMjctMjctOTQtOTR6bTI5My0yODctMjcgMjggOTQgOTQgMjctMjgtOTQtOTR6TTQzMiA4NjFjNDEuMzMgMCA3Ni44My0xNC42NyAxMDYuNS00NFM1ODMgNzUyIDU4MyA3MTBjMC00MS4zMy0xNC44My03Ni44My00NC41LTEwNi41UzQ3My4zMyA1NTkgNDMyIDU1OWMtNDIgMC03Ny42NyAxNC44My0xMDcgNDQuNXMtNDQgNjUuMTctNDQgMTA2LjVjMCA0MiAxNC42NyA3Ny42NyA0NCAxMDdzNjUgNDQgMTA3IDQ0em0wLTU1OWM0MS4zMyAwIDc2LjgzLTE0LjgzIDEwNi41LTQ0LjVTNTgzIDE5Mi4zMyA1ODMgMTUxYzAtNDItMTQuODMtNzcuNjctNDQuNS0xMDdTNDczLjMzIDAgNDMyIDBjLTQyIDAtNzcuNjcgMTQuNjctMTA3IDQ0cy00NCA2NS00NCAxMDdjMCA0MS4zMyAxNC42NyA3Ni44MyA0NCAxMDYuNVMzOTAgMzAyIDQzMiAzMDJ6bTI3NiAyODJjNDIgMCA3Ny42Ny0xNC44MyAxMDctNDQuNXM0NC02NS4xNyA0NC0xMDYuNWMwLTQyLTE0LjY3LTc3LjY3LTQ0LTEwN3MtNjUtNDQtMTA3LTQ0Yy00MS4zMyAwLTc2LjY3IDE0LjY3LTEwNiA0NHMtNDQgNjUtNDQgMTA3YzAgNDEuMzMgMTQuNjcgNzYuODMgNDQgMTA2LjVTNjY2LjY3IDU4NCA3MDggNTg0em0tNTU3IDBjNDIgMCA3Ny42Ny0xNC44MyAxMDctNDQuNXM0NC02NS4xNyA0NC0xMDYuNWMwLTQyLTE0LjY3LTc3LjY3LTQ0LTEwN3MtNjUtNDQtMTA3LTQ0Yy00MS4zMyAwLTc2LjgzIDE0LjY3LTEwNi41IDQ0UzAgMzkxIDAgNDMzYzAgNDEuMzMgMTQuODMgNzYuODMgNDQuNSAxMDYuNVMxMDkuNjcgNTg0IDE1MSA1ODR6IiBmaWxsPSIjZmZmIi8%2BPC9zdmc%2B)](https://aldaviva.testspace.com/spaces/270929) [![Coveralls](https://img.shields.io/coveralls/github/Aldaviva/SolCalc?logo=coveralls)](https://coveralls.io/github/Aldaviva/SolCalc?branch=master)\n\nFind when sunrise, sunset, and different twilights happen for a given location, based on the [NOAA ESRL Solar Calculator](https://gml.noaa.gov/grad/solcalc/).\n\nFeatures high accuracy across several millenia, atmospheric refraction, a simple enumeration-based API, and multiple/missing events during polar night/day/twilight at extreme latitudes.\n\n\u003c!-- MarkdownTOC autolink=\"true\" bracket=\"round\" autoanchor=\"false\" levels=\"1,2,3\" bullets=\"1.,-\" --\u003e\n\n1. [Prerequisites](#prerequisites)\n1. [Installation](#installation)\n1. [Quick Start](#quick-start)\n1. [Concepts](#concepts)\n    - [Sunlight levels](#sunlight-levels)\n    - [Solar times of day](#solar-times-of-day)\n1. [Usage](#usage)\n    - [Get the sunlight level at a time and location](#get-the-sunlight-level-at-a-time-and-location)\n    - [Get the series of sunlight level changes at a location starting after a time](#get-the-series-of-sunlight-level-changes-at-a-location-starting-after-a-time)\n1. [Algorithm](#algorithm)\n    - [Accuracy](#accuracy)\n\n\u003c!-- /MarkdownTOC --\u003e\n\n![Sun](https://raw.githubusercontent.com/Aldaviva/SolCalc/master/.github/images/readme-header.jpg)\n\n## Prerequisites\n\n- .NET runtime that conforms to [.NET Standard 2.0](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0) or later\n    - .NET 5 or later\n    - .NET Core 2.0 or later\n    - .NET Framework 4.6.1 or later\n\n## Installation\n\nThe [**`SolCalc`**](https://www.nuget.org/packages/SolCalc/) package is available on NuGet Gallery.\n\n```bat\ndotnet add package SolCalc\n```\n\n## Quick Start\n\n```cs\nusing NodaTime;\nusing NodaTime.Extensions;\nusing SolCalc;\nusing SolCalc.Data;\n\nZonedDateTime now = SystemClock.Instance.InZone(DateTimeZoneProviders.Tzdb[\"America/Los_Angeles\"]).GetCurrentZonedDateTime();\nconst double  lat = 37.35, lon = -121.95;\n\nSunlightLevel currentSunlight = SunlightCalculator.GetSunlightAt(now, lat, lon);\nSunlightChange nextSunrise = SunlightCalculator.GetSunlightChanges(now, lat, lon)\n    .First(change =\u003e change.Name == SolarTimeOfDay.Sunrise);\n\nConsole.WriteLine($\"It is currently {currentSunlight} in Santa Clara, CA, US.\");\nConsole.WriteLine($\"The next sunrise will be {nextSunrise.Time:l\u003cF\u003e x}.\");\n// It is currently AstronomicalTwilight in Santa Clara, CA, US.\n// The next sunrise will be Tuesday, April 23, 2024 6:23:01 am PDT.\n```\n\n## Concepts\n\nFor more information and diagrams, see [\"Twilight\" on Wikipedia](https://en.wikipedia.org/wiki/Twilight).\n\n### Sunlight levels\n\nQuantized levels of sunlight brightness based on the sun's angle above the horizon at 0°. These represent **durations** from one [solar time of day](#solar-times-of-day) to the next. Each twilight generally occurs twice per day.\n\n|Level|Solar elevation range|Description|\n|-|-:|-|\n|**Daylight**|[0°, 90°]|Sun is visible|\n|**Civil twilight**|[−6°, 0°)|Objects are visible|\n|**Nautical twilight**|[−12°, −6°)|Silhouettes are visible|\n|**Astronomical twilight**|[−18°, −12°)|Sunlight is only detectable with instruments|\n|**Night**|[−90°, −18°)|No sunlight|\n\n### Solar times of day\n\n**Instants** in a day when the [sunlight level](#sunlight-levels) changes from one level to another.\n\n|Time of day|Sun direction|Previous light level|New light level|Solar elevation|\n|-|-|-|-|-:|\n|**Astronomical dawn**|Rising|Night|Astronomical twilight|−18°|\n|**Nautical dawn**|Rising|Astronomical twilight|Nautical twilight|−12°|\n|**Civil dawn**|Rising|Nautical twilight|Civil twilight|−6°|\n|**Sunrise**|Rising|Civil twilight|Daylight|0°|\n|**Sunset**|Setting|Daylight|Civil twilight|0°|\n|**Civil dusk**|Setting|Civil twilight|Nautical twilight|−6°|\n|**Nautical dusk**|Setting|Nautical twilight|Astronomical twilight|−12°|\n|**Astronomical dusk**|Setting|Astronomical twilight|Night|−18°|\n\n## Usage\n\nThe main entry point into this library is the `SolCalc.SunlightCalculator` static class.\n\n### Get the sunlight level at a time and location\n\nUse `SunlightCalculator.GetSunlightAt(ZonedDateTime, double, double)` to return the [sunlight level](#sunlight-levels) at the given geographic coordinates at the given instant.\n\nThe instant's time zone must be the same zone that the given location observes, otherwise the result will be wrong. In the example below, Santa Clara, CA is in the `America/Los_Angeles` time zone.\n\n```cs\nusing NodaTime;\nusing NodaTime.Extensions;\nusing SolCalc;\nusing SolCalc.Data;\n\nDateTimeZone  zone = DateTimeZoneProviders.Tzdb[\"America/Los_Angeles\"];\nZonedDateTime now  = SystemClock.Instance.InZone(zone).GetCurrentZonedDateTime();\n\nSunlightLevel level = SunlightCalculator.GetSunlightAt(now, latitude: 37.35, longitude: -121.95);\nConsole.WriteLine($\"It is currently {level} in Santa Clara, CA, US.\");\n// It is currently Night in Santa Clara, CA, US.\n```\n\n### Get the series of sunlight level changes at a location starting after a time\n\nUse `SunlightCalculator.GetSunlightChanges(ZonedDateTime, double, double)` to get an infinite series of all future sunlight level changes at a particular location, starting after a given time.\n\nThe instant's time zone must be the same zone that the given location observes, otherwise the result will be wrong. In the example below, Santa Clara, CA is in the `America/Los_Angeles` time zone.\n\nThe returned `IEnumerable\u003cSunlightChange\u003e` is infinitely long because the sun will always rise again. It is not bounded by the end of the day. This means you should not try to call `.ToList()`, `.Count()`, or any other method that fully enumerates it, because they will never end. Instead, use filtering to get just the items you want, using methods like `.TakeWhile()`, `.SkipWhile()`, and `.First()`.\n\n#### Get the next sunlight level change at a location\n\n```cs\nDateTimeZone  zone = DateTimeZoneProviders.Tzdb[\"America/Los_Angeles\"];\nZonedDateTime now  = SystemClock.Instance.InZone(zone).GetCurrentZonedDateTime();\n\nSunlightChange nextChange = SunlightCalculator.GetSunlightChanges(now, latitude: 37.35, longitude: -121.95).First();\nConsole.WriteLine($\"At {nextChange.Time}, {nextChange.Name} will start when {nextChange.PreviousSunlightLevel} changes to {nextChange.NewSunlightLevel} in Santa Clara, CA, US.\");\n// At 2024-04-22T04:48:01 America/Los_Angeles (-07), AstronomicalDawn will start when Night changes to AstronomicalTwilight in Santa Clara, CA, US.\n```\n\n#### Get sunrise and sunset on a date at a location\n\n```cs\nDateTimeZone  zone = DateTimeZoneProviders.Tzdb[\"America/Los_Angeles\"];\nZonedDateTime now  = SystemClock.Instance.InZone(zone).GetCurrentZonedDateTime();\nIEnumerable\u003cSunlightChange\u003e dailySunriseAndSunset = SunlightCalculator.GetSunlightChanges(now, 37.35, -121.95)\n    .TakeWhile(s =\u003e s.Time.Date == now.Date).ToList();\n\nZonedDateTime? sunrise = dailySunriseAndSunset.FirstOrNull(s =\u003e s.Name == SolarTimeOfDay.Sunrise)?.Time;\nZonedDateTime? sunset  = dailySunriseAndSunset.FirstOrNull(s =\u003e s.Name == SolarTimeOfDay.Sunset)?.Time;\n```\n\n#### Wait for each sunlight level change\n\n```cs\nDateTimeZone zone  = DateTimeZoneProviders.Tzdb[\"America/Los_Angeles\"];\nZonedClock   clock = SystemClock.Instance.InZone(zone);\n\nIEnumerable\u003cSunlightChange\u003e sunlightChanges = SunlightCalculator.GetSunlightChanges(clock.GetCurrentZonedDateTime(), 37.35, -121.95);\nforeach (SunlightChange sunlightChange in sunlightChanges) {\n    Duration delay = sunlightChange.Time.Minus(clock.GetCurrentZonedDateTime());\n    Console.WriteLine($\"Waiting {delay} for {sunlightChange.Name} at {sunlightChange.Time}\");\n    await Task.Delay(delay.ToTimeSpan());\n\n    Console.WriteLine($\"It is currently {sunlightChange.Name} at {clock.GetCurrentZonedDateTime()} in Santa Clara, CA, US\");\n}\n```\n\n## Algorithm\n\nThis library uses the solar position calculation algorithm from the National Oceanic and Atmospheric Administration's Earth System Research Laboratories' Global Monitoring Laboratory's web-based [Solar Calculator](https://gml.noaa.gov/grad/solcalc/).\n\n\u003e [!WARNING]  \n\u003e For research and recreational use only. Not for legal use.\n\nIf you want to calculate solar position or solar noon, you can use the `SolarCalculator` static class.\n\n### Accuracy\n\n- Time accuracy decreases from \u0026#x2264; ±1 minute at latitudes \u0026#x2264; ±72°, to \u0026#x2264; ±10 minutes at latitudes \u0026gt; ±72°.\n- Atmospheric refraction is taken in account.\n- Clouds, air pressure, humidity, dust, other atmospheric conditions, observer's altitude, and solar eclipses are not taken into account.\n- Years between −2000 and 3000 can be handled.\n- Dates before October 15, 1582 might not use the correct calendar system.\n- Years between 1800 and 2100 have the highest accuracy results. Years between −1000 and 3000 have medium accuracy results. Years outside those ranges have lower accuracy results.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faldaviva%2Fsolcalc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faldaviva%2Fsolcalc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faldaviva%2Fsolcalc/lists"}