Skip to content

Commit

Permalink
Refactor pt.1 (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
davideilmito authored Mar 23, 2023
1 parent 6c1a50f commit 6779ccb
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 109 deletions.
90 changes: 58 additions & 32 deletions Sources/SunKit/Sun.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Foundation
import CoreLocation

public class Sun {

/*--------------------------------------------------------------------
Public get Variables
*-------------------------------------------------------------------*/
Expand Down Expand Up @@ -60,10 +61,6 @@ public class Sun {
public private(set) var decemberSolstice: Date = Date()


public static let common: Sun = {
return Sun(location: CLLocation(latitude: 37.334886, longitude: -122.008988), timeZone: -7, useSameTimeZone: true)
}()

public var azimuth: Angle {
return self.sunHorizonCoordinates.azimuth
}
Expand Down Expand Up @@ -168,27 +165,23 @@ public class Sun {
let timeZoneSeconds: Int = Int(newTimeZone * SECONDS_IN_ONE_HOUR)
timeZone = TimeZone(secondsFromGMT: timeZoneSeconds) ?? .current
location = newLocation
changeCurrentDate()
refresh()
}

public func setLocation(_ newLocation: CLLocation,_ newTimeZone: TimeZone) {
timeZone = newTimeZone
location = newLocation
changeCurrentDate()
refresh()
}

public func setTimeZone(_ newTimeZone: Double) {
let timeZoneSeconds: Int = Int(newTimeZone * SECONDS_IN_ONE_HOUR)
timeZone = TimeZone(secondsFromGMT: timeZoneSeconds) ?? .current
changeCurrentDate()
refresh()
}

public func setTimeZone(_ newTimeZone: TimeZone) {
timeZone = newTimeZone
changeCurrentDate()
refresh()
}

Expand Down Expand Up @@ -251,8 +244,8 @@ public class Sun {
private var dateFormatter: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.locale = .current
dateFormatter.timeZone = timeZone
dateFormatter.timeStyle = .full
dateFormatter.timeZone = useSameTimeZone ? .current : self.timeZone
dateFormatter.timeStyle = useSameTimeZone ? .short : .full
dateFormatter.dateStyle = .full
return dateFormatter
}
Expand Down Expand Up @@ -343,16 +336,10 @@ public class Sun {
self.lastLight = getLastLight() ?? Date()
}

self.marchEquinox = getMarchEquinox()
self.juneSolstice = getJuneSolstice()
self.septemberEquinox = getSeptemberEquinox()
self.decemberSolstice = getDecemberSolstice()
}

/// function called after timezone changes in order to change the date accordingly
private func changeCurrentDate(){
let components = calendar.dateComponents(in: self.timeZone, from: self.date)
self.date = calendar.date(from: components) ?? self.date
self.marchEquinox = getMarchEquinox() ?? Date()
self.juneSolstice = getJuneSolstice() ?? Date()
self.septemberEquinox = getSeptemberEquinox() ?? Date()
self.decemberSolstice = getDecemberSolstice() ?? Date()
}

private func getSunMeanAnomaly(from elapsedDaysSinceStandardEpoch: Double) -> Angle {
Expand Down Expand Up @@ -585,49 +572,88 @@ public class Sun {
return firstLight
}

private func getMarchEquinox() -> Date {
private func convertComponentsInCurrentTimeZoneDate(_ components: DateComponents) -> Date?{

var dateCurrentTimeZone = calendar.date(from: components)
dateCurrentTimeZone = calendar.date(bySetting: .day, value: components.day ?? 23, of: dateCurrentTimeZone ?? Date())
dateCurrentTimeZone = calendar.date(bySetting: .month, value: components.month ?? 23, of: dateCurrentTimeZone ?? Date())
dateCurrentTimeZone = calendar.date(bySetting: .year, value: components.year ?? 23, of: dateCurrentTimeZone ?? Date())
dateCurrentTimeZone = calendar.date(bySettingHour: components.hour ?? 23, minute: components.minute ?? 59, second: components.second ?? 59,of: dateCurrentTimeZone ?? Date())

return dateCurrentTimeZone

}

private func getMarchEquinox() -> Date? {

let year = Double(calendar.component(.year, from: self.date))
let t: Double = year / 1000
let julianDayMarchEquinox: Double = 1721139.2855 + 365.2421376 * year + 0.0679190 * pow(t, 2) - 0.0027879 * pow(t, 3)

let marchEquinoxUTC = dateFromJd(jd: julianDayMarchEquinox)
let components = calendar.dateComponents(in: self.timeZone, from: marchEquinoxUTC)
return calendar.date(from: components) ?? Date()
if(!useSameTimeZone){

return marchEquinoxUTC
}else{

let components = calendar.dateComponents(in: self.timeZone, from: marchEquinoxUTC)
return convertComponentsInCurrentTimeZoneDate(components)
}
}

private func getJuneSolstice() -> Date {
private func getJuneSolstice() -> Date? {

let year = Double(calendar.component(.year, from: self.date))
let t: Double = year / 1000
let julianDayJuneSolstice: Double = 1721233.2486 + 365.2417284 * year - 0.0530180 * pow(t, 2) + 0.0093320 * pow(t, 3)

let juneSolsticeUTC = dateFromJd(jd: julianDayJuneSolstice)
let components = calendar.dateComponents(in: self.timeZone, from: juneSolsticeUTC)
return calendar.date(from: components) ?? Date()

if(!useSameTimeZone){

return juneSolsticeUTC
}else{

let components = calendar.dateComponents(in: self.timeZone, from: juneSolsticeUTC)
return convertComponentsInCurrentTimeZoneDate(components)
}

}

private func getSeptemberEquinox() -> Date {
private func getSeptemberEquinox() -> Date? {

let year = Double(calendar.component(.year, from: self.date))
let t: Double = year / 1000
let julianDaySeptemberEquinox: Double = 1721325.6978 + 365.2425055 * year - 0.126689 * pow(t, 2) + 0.0019401 * pow(t, 3)

let septemberEquinoxUTC = dateFromJd(jd: julianDaySeptemberEquinox)
let components = calendar.dateComponents(in: self.timeZone, from: septemberEquinoxUTC)
return calendar.date(from: components) ?? Date()

if(!useSameTimeZone){

return septemberEquinoxUTC
}else{

let components = calendar.dateComponents(in: self.timeZone, from: septemberEquinoxUTC)
return convertComponentsInCurrentTimeZoneDate(components)
}
}

private func getDecemberSolstice() -> Date {
private func getDecemberSolstice() -> Date? {

let year = Double(calendar.component(.year, from: self.date))
let t: Double = year / 1000
let julianDayDecemberSolstice: Double = 1721414.3920 + 365.2428898 * year - 0.0109650 * pow(t, 2) - 0.0084885 * pow(t, 3)

let decemberSolsticeUTC = dateFromJd(jd: julianDayDecemberSolstice)
let components = calendar.dateComponents(in: self.timeZone, from: decemberSolsticeUTC)
return calendar.date(from: components) ?? Date()

if(!useSameTimeZone){

return decemberSolsticeUTC
}else{

let components = calendar.dateComponents(in: self.timeZone, from: decemberSolsticeUTC)
return convertComponentsInCurrentTimeZoneDate(components)
}
}

}
58 changes: 31 additions & 27 deletions Tests/SunKitTests/UT_Sun.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,32 +65,6 @@ final class UT_Sun: XCTestCase {
static let timeZoneMumbai = 5.5


/// Test of a sun ionstance whenm you play with timezones and change location
func testOfSunWhenTimezoneChanges() throws {

//Step1: Creating Sun instance in Naples and with timezone +1
let timeZoneNaples: TimeZone = .init(secondsFromGMT: UT_Sun.timeZoneNaples * Int(SECONDS_IN_ONE_HOUR)) ?? .current
var sunUnderTest = Sun.init(location: UT_Sun.naplesLocation, timeZone: timeZoneNaples)

//Step2: Setting 19/11/22 20:00 as date. (No daylight saving)
let dateUnderTest = createDateCustomTimeZone(day: 19, month: 11, year: 2022, hour: 20, minute: 00, seconds: 00,timeZone: timeZoneNaples)
sunUnderTest.setDate(dateUnderTest)

//Step3: Change location and timezone
let timeZoneTokyo: TimeZone = .init(secondsFromGMT: UT_Sun.timeZoneTokyo * Int(SECONDS_IN_ONE_HOUR)) ?? .current
sunUnderTest.setLocation(UT_Sun.tokyoLocation, timeZoneTokyo)

//Step4: Saving expected outputs for all the date
let expectedDate = createDateCustomTimeZone(day: 20, month: 11, year: 2022, hour: 4, minute: 00, seconds: 00,timeZone: timeZoneTokyo)

//Step5: Check if output of sunUnderTest.date matches the expected output
XCTAssertTrue(expectedDate == sunUnderTest.date)



}


/// Test of Sun azimuth, sunrise, sunset, afternoon golden hour start and afternoon golden hour end
/// Value for expected results have been taken from SunCalc.org
func testOfSun() throws {
Expand Down Expand Up @@ -338,6 +312,15 @@ final class UT_Sun: XCTestCase {

//Step4: Check if the output are close to the expected ones

XCTAssertTrue(abs(expectedAzimuth - sunUnderTest.azimuth.degrees) < UT_Sun.sunAzimuthThreshold)
XCTAssertTrue(abs(expectedAltitude - sunUnderTest.altitude.degrees) < UT_Sun.sunAltitudeThreshold)

XCTAssertTrue(abs(expectedSunRise.timeIntervalSince1970 - sunUnderTest.sunrise.timeIntervalSince1970) < UT_Sun.sunSetRiseThresholdInSeconds)
XCTAssertTrue(abs(expectedSunset.timeIntervalSince1970 - sunUnderTest.sunset.timeIntervalSince1970) < UT_Sun.sunSetRiseThresholdInSeconds)
XCTAssertTrue(abs(expectedFirstLight.timeIntervalSince1970 - sunUnderTest.firstLight.timeIntervalSince1970) < UT_Sun.sunSetRiseThresholdInSeconds)
XCTAssertTrue(abs(expectedLastLight.timeIntervalSince1970 - sunUnderTest.lastLight.timeIntervalSince1970) < UT_Sun.sunSetRiseThresholdInSeconds)
XCTAssertTrue(abs(expectedSolarNoon.timeIntervalSince1970 - sunUnderTest.solarNoon.timeIntervalSince1970) < UT_Sun.sunSetRiseThresholdInSeconds)

}

func testOfEquinoxesAndSolstices() throws {
Expand Down Expand Up @@ -375,7 +358,28 @@ final class UT_Sun: XCTestCase {
}



/// Test of a sun ionstance whenm you play with timezones and change location
func testOfSunWhenTimezoneChanges() throws {

//Step1: Creating Sun instance in Naples and with timezone +1
let timeZoneNaples: TimeZone = .init(secondsFromGMT: UT_Sun.timeZoneNaples * Int(SECONDS_IN_ONE_HOUR)) ?? .current
let sunUnderTest = Sun.init(location: UT_Sun.naplesLocation, timeZone: timeZoneNaples)

//Step2: Setting 19/11/22 20:00 as date. (No daylight saving)
let dateUnderTest = createDateCustomTimeZone(day: 19, month: 11, year: 2022, hour: 20, minute: 00, seconds: 00,timeZone: timeZoneNaples)
sunUnderTest.setDate(dateUnderTest)

//Step3: Change location and timezone
let timeZoneTokyo: TimeZone = .init(secondsFromGMT: UT_Sun.timeZoneTokyo * Int(SECONDS_IN_ONE_HOUR)) ?? .current
sunUnderTest.setLocation(UT_Sun.tokyoLocation, timeZoneTokyo)

//Step4: Saving expected outputs for all the date
let expectedDate = createDateCustomTimeZone(day: 20, month: 11, year: 2022, hour: 4, minute: 00, seconds: 00,timeZone: timeZoneTokyo)

//Step5: Check if output of sunUnderTest.date matches the expected output
XCTAssertTrue(expectedDate == sunUnderTest.date)

}



Expand Down
Loading

0 comments on commit 6779ccb

Please sign in to comment.