Coder Social home page Coder Social logo

solar's Introduction

Solar

Version Carthage compatible POD compatible SPM compatible Build Status MIT licensed

A Swift helper for generating Sunrise and Sunset times.

Solar performs its calculations locally using an algorithm from the United States Naval Observatory, and thus does not require the use of a network.

Usage

Solar simply needs a date and a location specified as a latitude and longitude:

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

We can also omit providing a date if we just need the sunrise and sunset for the current date and time:

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

Note that all dates are UTC. Don't forget to format your date into the appropriate timezone if required.

Types of sunrise and sunset

There are several types of sunrise and sunset that Solar generates. They differ by how many degrees the sun lies below the horizon:

  • Official (~0°)

  • Civil (6° below horizon)

  • Nautical (12° below horizon)

  • Astronomical (18° below horizon)

For more information, see https://www.timeanddate.com/astronomy/different-types-twilight.html

Convenience methods

Solar also comes packaged with some convenience methods:

// 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

Installation

Solar is available through CocoaPods, Carthage, and Swift Package Manager.

CocoaPods

To include Solar in an application, add the following pod to your Podfile, then run pod install:

pod "Solar-dev", "~> 3.0"

To include Solar in another pod, add the following dependency to your podspec:

s.dependency "Solar", "~> 3.0"

Carthage

Add the ceek/Solar project to your Cartfile, then follow the rest of Carthage’s XCFramework installation instructions:

github "ceeK/Solar" ~> 3.0

Swift Package Manager

To include Solar in an application in Xcode:

  1. Go to File ‣ Swift Packages ‣ Add Package Dependency.
  2. Enter https://github.com/ceeK/Solar.git as the package repository and click Next.
  3. Set Rules to Version, Up to Next Major, and enter 3.0.0 as the minimum version requirement. Click Next.

To include Solar in another Swift package, add the following dependency to your Package.swift:

.package(name: "Solar", url: "https://github.com/ceeK/Solar.git", from: "3.0.0")

License

The MIT License (MIT)

Copyright (c) 2016-2021 Chris Howell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

solar's People

Contributors

1ec5 avatar 3lvis avatar abdulajet avatar ceek avatar chezzdev avatar lucien avatar mateuszmackowiak avatar maximalien avatar raysarebest avatar readmecritic avatar rjourde avatar ronkliffer avatar yunnnyunnn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

solar's Issues

Sunrise and Sunset dates off by 1 day.

It seems that the dates are 1 day in the future if the local time is the next day UTC.

Not sure if this is the same problem as reported in #24?

Here is a complete test. Note that the reported times are one day in the future from the correct times.

    ///    Sun and Moon Data for One Day
    ///
    ///    U.S. Naval Observatory
    ///    Astronomical Applications Department
    ///
    ///    (Longitude W 94° 0', Latitude N 39° 0')
    ///
    ///    Friday, May 3, 2019    Universal Time - 5h
    ///    Sun
    ///    Begin civil twilight    05:47
    ///    Sunrise    06:16
    ///    Sun transit    13:13
    ///    Sunset    20:11
    ///    End civil twilight    20:40
    ///    Moon
    ///    Moonrise    05:56
    ///    Moon transit    12:24
    ///    Moonset    19:00
    ///
    /// [https://aa.usno.navy.mil/data/docs/RS_OneDay.php](https://aa.usno.navy.mil/data/docs/RS_OneDay.php)
    func testPlainLatLon() {
        var tdf: DateFormatter = {
            let df = DateFormatter()
            df.dateFormat = "MM/dd/yyyy HH:mm zzz"
            return df
        }()
        let testCriticalEvening = tdf.date(from: "05/03/2019 19:20 CDT")!
        let testLocation: CLLocation = CLLocation(latitude: 39.00, longitude: -94.0)
        let expectedSunrise = "05/03/2019 06:16 CDT"
        let expectedSunset = "05/03/2019 20:11 CDT"
        let solar = Solar(for: testCriticalEvening, coordinate: testLocation.coordinate)

        XCTAssert(tdf.string(from: solar!.sunrise!) == expectedSunrise,
                  "Expected: \(expectedSunrise), Received: \(tdf.string(from: solar!.sunrise!))")
        XCTAssert(tdf.string(from: solar!.sunset!) == expectedSunset,
                  "Expected: \(expectedSunset), Received: \(tdf.string(from: solar!.sunset!))")
    }

The results of the test are:

UI Test Activity: 
Assertion Failure: Solar_iOSTests.swift:198: XCTAssertTrue failed - Expected: 05/03/2019 06:16 CDT, Received: 05/04/2019 06:14 CDT

UI Test Activity: 
Assertion Failure: Solar_iOSTests.swift:200: XCTAssertTrue failed - Expected: 05/03/2019 20:11 CDT, Received: 05/04/2019 20:11 CDT

Xcode 10 build error

After updating Xcode to version 10, it shows me the following error on import Solar:
Module compiled with Swift 4.1.2 cannot be imported by the Swift 4.2 compiler.
Any ideas how to fix this?

Day Light Saving Issue

When using Solar.init(for: self.datePicker.dateValue, coordinate: coordinate)
I am having inconsistent results when dls changes.. Just to be sure, does your code calculate
DLS changes or am i doing something wrong.

Just to be more clear here is my result set:

2018-10-08

Santa Monica - California

dls for santa monica = true
sunrise of Santa Monica : 06:53:32
sunset of Santa Monica : 18:28:59

Istanbul - Turkey

dls for istanbul = false
sunrise of Istanbul : 07:07:28
sunset of Istanbul : 18:35:24

2018-11-08

Santa Monica - California

dls for santa monica = false
sunrise of Santa Monica : 07:19:52	**<- Wrong + 1 Hour**
sunset of Santa Monica : 17:55:15	**<- Wrong + 1 Hour**

Istanbul - Turkey

dls for istanbul = false
sunrise of Istanbul : 07:42:44
sunset of Istanbul : 17:52:28

if you need the project : https://github.com/kbirand/SolarTest
Thanks,
Koray Birand

Is it possible to get the times for a given sun position on a given date ?

Dear Chris,

Here is an example of what I mean:
Knowing the latitude, longitude of a location (Let's say: 40.730610, -73.935242 for New York) and knowing the sun angle (for example for the sunset the sun angle is defined as making an angle of -0.833 below the horizon) can I get the time of the sunset for a given date (for example: 6:22 AM on the 12th of July) ?

Of course, here I gave an example for the sunset but I want to get times for different sun angles.

So the call to the function would be like:
getTimeForGivenSunAngle(date,lat,long,sunAngle)
that will return something like: "In New York, on the 12th of July the Sun will make an angle of -0.833 degrees at 6:22 AM"

Best regards,

Michael

Xcode 12.5 Build Warning

I get the following build warning when building with Xcode 12.5:

/Users/me/Library/Developer/Xcode/DerivedData/Project/SourcePackages/checkouts/Solar/Package.swift The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.5.99.

This appears to have been fixed for Solar.podspec by 07e6310. Solar's Package.swift was likely overlooked. Please update the Package.swift deployment target to be consistent with the Solar.podspec.

Data used is inconsistent with other sources

EDIT: I was mistaken in that I was testing phone locations and forgot to switch back to default thus was getting data for a remote location.

The times given for setting/rising events is consistently off by up to an hour with respect to simply googling or found at www.timeanddate.com

For example on June 17th, 2017 in San Diego, California gives:
Sunrise starts: 3:52:09 AM
Sunrise ends: 5:47:13 AM
Sunset starts: 8:33:50 PM
Sunset ends: 10:28:56 PM

Google gives:
Sunrise: 5:41 AM
Sunset: 7:59 PM

and www.timeanddate.com giving same results as google +/- a minute or so.

Inconsistencies like this are found with every date I have seen

Update documentation

Update the docs to show that the Solar() constructor no longer accepts latitude and longitude as arguments, but requires an instance of CLLocationCoordinate2D instead

isNighttime calculation incorrect

official sunset today (2/12/17) was 5:45 pm in San Francisco. The isNighttime method returned true at 5:31 pm.

I believe this is because it's using Date() without a time zone to calculate when sunset is. However, in Pacific timezone, it is already reporting GMT sunset for 2/14

Return only time

Is it possible to return only the hours and minutes of the sunset or sunrise?

Timezone handling is putting date to one day ahead and daylight savings is not being processed

Hi Chris,

I think I've found an issue to do with time zones. When calling Solar with my lat/long (latitude: -38.2613, longitude: 145.1896), the returned date is always one day ahead of the for-date for all times (sunset, sunrise, all modes). Also, daylight savings is not being processed for my timezone (Melbourne, Australia)

I think the day-ahead problem may stem from line 188;

let localT = UT + (Double(timeZone.secondsFromGMT) / 3600.0)

as this pushes the "hour" variable in the following line;

let hour = floor(localT)

into numbers between 24 and 48 (i.e. the next day)

I tried fixing this up by putting the hour back into 0-24 hour range, but this mucked up the minute and second calculations. So, I had a think about timezones and went back to the underlying returned NSDate being an absolute number of seconds, regardless of timezone and that all your calculations were for UTC time. Given this, I (hack) changed line 188 to do nothing as follows;

let localT = UT

and replaced line 199;

var date = calendar.dateFromComponents(components)

with;

calendar.timeZone = NSTimeZone(abbreviation: "UTC")!
return calendar.dateFromComponents(components)

By changing the the time zone to suit your calculated UTC time, the returned NSDate will be the correct absolute number of seconds and any code using the returned NSDate will have the appropriate timezone set. This means the time zone calculations for the calling apps purposes will all be handled by the Swift libraries. As a side effect of getting the day correct, this also fixed up the issue where daylight savings was not being handled correctly.

NB: the early return I added in line 200 intentionally means lines 202 onwards are not called as they are no longer required.

I tested this fix for both Melbourne, Australia and London, England. It got the correct day, time and daylight savings was processed correctly. What do you think?

Cheers, Graham.

Solar Noon

Any chance of adding Solar Noon option?

isDaytime and isNightTime return incorrect values for polar day

For places where there's a polar day in the given time/date (see the example), isDaytime returns false and isNightTime returns true for all times of day (just opposite to reality).

Code:

private func isSunUp(dateTime: Date, coords: LatLon) -> Bool {
    let solar = Solar(for: dateTime, coordinate: CLLocationCoordinate2D(latitude: coords.lat, longitude: coords.lon))
    return solar!.isDaytime
}

Params:
dateTime: 2022-06-03 06:00:00 +0000
coords: lat: 67.94753132376813, lon: 13.131613209843637

Adding of 1 day to sunrise and sunset times happens too early

I'm in mexico city and noticed that the isDayTime returns false at exactly 18:00 local time (12:00 UTC) while current sunset time is around 20:15. After some analyses I found out that, at exactly that 12:00 UTC, the sunrise and sunset days are shifted one day forward. This results in both sunrise and sunset being later than the current time, which results in false for isDayTime.

I'm assuming this 1 day shift should only happen after sunset, right?

I really appreciate what you've done, and, honestly it goes a bit over my head. I understand that eventually the result of this code is probably wrong:

        let shouldBeYesterday = lngHour > 0 && UT > 12 && sunriseSunset == .sunrise
        let shouldBeTomorrow = lngHour < 0 && UT < 12 && sunriseSunset == .sunset

but I guess it's also very well possible, that is somewhere in the code above these lines.

These are the values for lngHour & UT (after normalisation) for sunrise and sunset respectively, in my location, mexico city:

lat: 19.39258888
lon: -99.28117439
lngHour: -6.61874495933333
UT sunrise: 11.9693350962159
UT sunset: 1.24306218714151

I could work around this by adding a day to the currentTime calculation if date > 12:00 UTC, but I'm not sure is a good idea. From what I've seen here it works for most people, so might be something with my location specifically, while the App I'm using this in is used all over the world.

Any thoughts to a fix or workaround?

error when excute carthage update

There is error when I adding Solar to my project with carthage and hope you can check it out :)
log:
*** Fetching Solar
*** Checking out Solar at "2.0.0"
*** xcodebuild output can be found in /var/folders/0m/bv501p9j043_w386gf5g7dlh0000gn/T/carthage-xcodebuild.vDSKOj.log
*** Building scheme "Solar" in Solar.xcodeproj
Build Failed
Task failed with exit code 65:
/usr/bin/xcrun xcodebuild -project
.../Carthage/Checkouts/Solar/Solar.xcodeproj -scheme Solar -configuration Release -derivedDataPath /Users/brucewzp/Library/Caches/org.carthage.CarthageKit/DerivedData/Solar/2.0.0 -sdk iphoneos ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES clean build

This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/0m/bv501p9j043_w386gf5g7dlh0000gn/T/carthage-xcodebuild.vDSKOj.log

Update to Swift 3 syntax.

As Swift 3 has now entered beta, the project will need to be updated.

A develop branch will need to be made to house these changes before Swift 3 goes gold.

calculate function uses hard coded "Official" rather than passed-in zenith

Hi Chris,

Thank you loads for the work porting the calculations to Swift, it's been very helpful!

In testing I found the sunset times for offical, civil, etc., were all the same. In Solar.swift on line 162, I noticed the calculate function was not using the passed-in zenith and was instead always using the "Official" zenith;

   let cosH = (cos(Zenith.Official.rawValue.degreesToRadians) - (sinDec * sin(latitude.degreesToRadians))) / (cosDec * cos(latitude.degreesToRadians))

This can be corrected with the following;

   let cosH = (cos(zenith.rawValue.degreesToRadians) - (sinDec * sin(latitude.degreesToRadians))) / (cosDec * cos(latitude.degreesToRadians))

Cheers, Graham.

Late sunsets give incorrect date for time zone

I'm getting an issue with putting in a date that is after midnight UTC but before midnight local. It returns a solar instance for the following day. I've tried passing in a custom calendar but that doesn't seem to fix the issue. I'll continue working on it but for now here's a test I wrote to recreate this failure case.

	func testLateTimeCorrectReturnDate() {
		let lateTime = Date(timeIntervalSince1970: 1499130000) // After midnight UTC, before midnight in DC.
		let city = cities.first(where: { $0.name == "Washington, D. C." })!
		
		let calendar: Calendar = {
			var calendar = Calendar.current
			calendar.timeZone = TimeZone(identifier: "EST")!
			return calendar
		}()
		
		guard let solar = Solar(for: lateTime, latitude: city.latitude, longitude: city.longitude) else {
			XCTFail("Cannot get solar")
			return
		}
		
		let sameDate = calendar.compare(lateTime, to: solar.sunset!, toGranularity: .day)
		
		XCTAssertTrue(sameDate == .orderedSame, "The sunset given \(solar.sunset!) is not same day as given date \(lateTime)")
	}

Support installation via Carthage for macOS and tvOS

According to the CocoaPods podspec, this project supports macOS 10.9+ and tvOS 9.0+ alongside iOS. However, the Xcode project only has a scheme for iOS, which means this library can’t be installed for a macOS or tvOS project using Carthage. The fix would be to add two additional framework targets, two additional schemes, and the required entries in the Travis configuration file.

Remove need for supplying timezone

It seems as if the timezone shouldn't strictly be necessary. If we calculate the UTC time of sunrise, we should be able to convert it to the appropriate timezone within the client application.

Right now, removing the timezone results in sunrises happening in the evening of the supplied date. The sunrise obviously can't be 8pm on the 2nd April if the user supplied 2nd April.

A little bit of magic should be needed.

Mismatched times when device timezone and input lat/lon are different

I am getting some incorrect results on my iOS simulator with the following conditions:

  • IOS simulator timezone PDT (in California)
  • Lat/Lon for solar events: latitude: 32.845753, longitude: -96.852206 (Dallas, Texas)

Returned results:

solarEvent: Optional(Solar.Solar(coordinate: __C.CLLocationCoordinate2D(latitude: 32.845753, longitude: -96.852206), date: 2023-03-27 04:46:28 +0000, sunrise: Optional(2023-03-27 12:22:16 +0000), sunset: Optional(2023-03-28 00:43:56 +0000), civilSunrise: Optional(2023-03-27 11:57:33 +0000), civilSunset: Optional(2023-03-28 01:08:40 +0000), nauticalSunrise: Optional(2023-03-27 11:28:37 +0000), nauticalSunset: Optional(2023-03-28 01:37:37 +0000), astronomicalSunrise: Optional(2023-03-27 10:59:16 +0000), astronomicalSunset: Optional(2023-03-28 02:07:00 +0000)))
for lat, lon: 32.845753 -96.852206

These results in GMT are all exactly two hours earlier than would be the correct times in Dallas. This seems to correlate with the two hour time difference between my simulator (PDT) and the lat/lon given (CDT).

Possible cause:
The Solar struct initializes its property 'self.date' using Date(), which will take the time from the device. So when the solar events are requested in a timezone different from the device this can lead to a time offset.

I hope this helps!

Add tests

This will need fleshing out, but a good test suite would add confidence in using the library. Quick + Nimble preferred.

WeatherKit

WeatherKit has a CurrentWeather.isDaylight property and SunEvents struct that essentially replicate the functionality of this library. However, WeatherKit is only available for this year’s operating system releases (iOS 16, iPadOS 16, macOS 13, tvOS 16, watchOS 9). Should this library somehow integrate with WeatherKit on supported platforms, perhaps becoming a compatibility shim for it on unsupported Swift platforms like Linux?

Daylight Saving time

Could it be that Solar doesn't take daylight saving time into account? I live in Mexico City and we're currently on DST. Sunset is around 8:10 PM now, but Solar thinks it's at 7:10 PM

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.