Update/0.0.9 (#9)

* Made Coordinate, Aspect and Lunation conform to Codable

* Remove TimeZone parameter from RiseTime and SetTime
This commit is contained in:
Vincent Smithers 2021-11-09 09:25:27 -05:00 committed by GitHub
parent 0fb72e0a80
commit cfb98b77a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 110 additions and 105 deletions

View File

@ -8,7 +8,7 @@
import Foundation
/// Models a geometric aspect between two bodies.
public enum Aspect: Equatable, Hashable {
public enum Aspect: Equatable, Hashable, Codable {
/// A 0° alignment.
case conjunction(Double)

View File

@ -73,3 +73,43 @@ public struct Coordinate<T: CelestialBody> {
extension Coordinate: ZodiacCoordinate {
public var value: Double { longitude }
}
// MARK: - Codable Conformance
extension Coordinate: Codable {
public enum CodingKeys: CodingKey {
case body
case date
case longitude
case latitude
case distance
case speedLongitude
case speedLatitude
case speedDistance
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
body = try container.decode(T.self, forKey: .body)
date = try container.decode(Date.self, forKey: .date)
longitude = try container.decode(Double.self, forKey: .longitude)
latitude = try container.decode(Double.self, forKey: .latitude)
distance = try container.decode(Double.self, forKey: .distance)
speedLongitude = try container.decode(Double.self, forKey: .speedLongitude)
speedLatitude = try container.decode(Double.self, forKey: .speedLatitude)
speedDistance = try container.decode(Double.self, forKey: .speedDistance)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(body, forKey: .body)
try container.encode(date, forKey: .date)
try container.encode(longitude, forKey: .longitude)
try container.encode(latitude, forKey: .latitude)
try container.encode(distance, forKey: .distance)
try container.encode(speedLongitude, forKey: .speedLongitude)
try container.encode(speedLatitude, forKey: .speedLatitude)
try container.encode(speedDistance, forKey: .speedDistance)
}
}

View File

@ -13,7 +13,7 @@ import CSwissEphemeris
public struct Lunation {
/// Represents common phases of the moon.
public enum Phase: Int {
public enum Phase: Int, Codable {
/// Less than one percent full.
case new
/// 1 to 50 percent towards full.
@ -51,7 +51,7 @@ public struct Lunation {
/// The percentage full.
public let percentage: Double
/// Lunation is moving towards full
let isWaxing: Bool
public let isWaxing: Bool
/// The current `Phase`.
public var phase: Phase { Phase(lunation: self) }
/// The pointer that holds all values.
@ -81,3 +81,30 @@ public struct Lunation {
isWaxing = percentage > pointerFuture[1]
}
}
// MARK: - Codable Conformance
extension Lunation: Codable {
public enum CodingKeys: CodingKey {
case date
case percentage
case isWaxing
case phase
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
date = try container.decode(Date.self, forKey: .date)
percentage = try container.decode(Double.self, forKey: .percentage)
isWaxing = try container.decode(Bool.self, forKey: .isWaxing)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(date, forKey: .date)
try container.encode(percentage, forKey: .percentage)
try container.encode(isWaxing, forKey: .isWaxing)
try container.encode(phase, forKey: .phase)
}
}

View File

@ -29,7 +29,7 @@ public protocol BatchRequest {
// MARK: - Helper Methods
extension BatchRequest {
public extension BatchRequest {
/// Helper method that prepares a collection of dates so that they can be mapped to the `EphemerisItem`.
/// - Parameters:

View File

@ -10,6 +10,8 @@ import Foundation
/// Models a sidereal coordinate on the Zodiac.
public struct SiderealCoordinate<T: CelestialBody> {
///
public let date: Date
/// The coordinate to set
private let coordinate: Coordinate<T>
/// The ayanamsha value that determines the sidereal position
@ -19,6 +21,7 @@ public struct SiderealCoordinate<T: CelestialBody> {
/// - Parameter coordinate: The coordinate to set.
/// - Parameter ayanamshaValue: The ayanamsha value that determines the sidereal position.
public init(coordinate: Coordinate<T>, ayanamshaValue: Double = Ayanamsha.current) {
self.date = coordinate.date
self.coordinate = coordinate
self.ayanamshaValue = ayanamshaValue
}

View File

@ -21,7 +21,6 @@ public struct RiseTime<T: CelestialBody> {
/// Creates a `RisingTime`.
/// - Parameters:
/// - timeZone: The `TimeZone` for the rise.
/// - date: The date to set for the rise.
/// - body: The celestial body that is rising.
/// - longitude: The longitude of the location.
@ -29,8 +28,7 @@ public struct RiseTime<T: CelestialBody> {
/// - altitude: The height above sea level. The default value is zero.
/// - atmosphericPressure: The level of atmospheric pressure. The default value is zero.
/// - atmosphericTemperature: The atmospheric temperature. The default value is zero.
public init(timeZone: TimeZone = TimeZone.current,
date: Date,
public init(date: Date,
body: T,
longitude: Double,
latitude: Double,
@ -56,6 +54,6 @@ public struct RiseTime<T: CelestialBody> {
time,
nil)
}
self.date = Date(julianDate: time[0]).addingTimeInterval(TimeInterval(timeZone.secondsFromGMT()))
self.date = Date(julianDate: time[0])
}
}

View File

@ -21,7 +21,6 @@ public struct SetTime<T: CelestialBody> {
/// Creates an instance of `SetTime`.
/// - Parameters:
/// - timeZone: The `TimeZone` for the set.
/// - date: The date to set for the set.
/// - body: The celestial body that is setting.
/// - longitude: The longitude of the location.
@ -29,8 +28,7 @@ public struct SetTime<T: CelestialBody> {
/// - altitude: The height above sea level. The default value is zero.
/// - atmosphericPressure: The level of atmospheric pressure. The default value is zero.
/// - atmosphericTemperature: The atmospheric temperature. The default value is zero.
public init(timeZone: TimeZone = TimeZone.current,
date: Date,
public init(date: Date,
body: T,
longitude: Double,
latitude: Double,
@ -56,6 +54,6 @@ public struct SetTime<T: CelestialBody> {
time,
nil)
}
self.date = Date(julianDate: time[0]).addingTimeInterval(TimeInterval(timeZone.secondsFromGMT()))
self.date = Date(julianDate: time[0])
}
}

View File

@ -1,35 +0,0 @@
//
// LunationsRequest.swift
//
//
// Created by Vincent on 6/29/21.
//
import Foundation
/// A `BatchRequest` for a collection of `Lunation`.
final public class LunationsRequest: BatchRequest {
public typealias EphemerisItem = Lunation
public let datesThreshold = 478
/// Creates an instance of `LunationsRequest`.
public init() {}
public func fetch(start: Date, end: Date, interval: TimeInterval = 60.0, _ closure: ([EphemerisItem]) -> Void) {
var lunations = [EphemerisItem]()
let group = DispatchGroup()
func execute(batches: [[Date]], _ closure: ([EphemerisItem]) -> Void) {
guard let batch = batches.first else {
closure(lunations)
return
}
group.enter()
let c = batch.map { EphemerisItem(date: $0) }
lunations.append(contentsOf: c)
group.leave()
execute(batches: Array(batches.dropFirst()), closure)
}
execute(batches: dates(for: start, end: end, interval: interval), closure)
}
}

View File

@ -247,59 +247,44 @@ final class CelestialBodyTests: XCTestCase {
let ayanamsha = Ayanamsha()(for: date)
XCTAssertEqual((ayanamsha * 100).rounded() / 100, 25.04)
}
func testPlanetRisingTime() throws {
let timestamp = "2021-03-14"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = try XCTUnwrap(dateFormatter.date(from: timestamp))
let timeZone = try XCTUnwrap(TimeZone(abbreviation: "CEST"))
let sunrise = RiseTime<Planet>(timeZone: timeZone,
date: date,
body: .sun,
longitude: 13.41053,
latitude: 52.52437,
altitude: 0)
XCTAssertEqual(sunrise.date?.description, "2021-03-14 07:22:32 +0000")
let californiaTimeZone = try XCTUnwrap(TimeZone(identifier: "America/Los_Angeles"))
let sunriseSantaCruz = RiseTime<Planet>(timeZone: californiaTimeZone,
date: date,
body: .sun,
longitude: -122.0297222,
latitude: 36.9741667,
altitude: 0)
XCTAssertEqual(sunriseSantaCruz.date?.description, "2021-03-14 07:19:44 +0000")
let dateB = try XCTUnwrap(dateFormatter.date(from: "2021-03-15"))
let newYorkTimeZone = try XCTUnwrap(TimeZone(identifier: "America/New_York"))
let moonRiseNYC = RiseTime<Planet>(timeZone: newYorkTimeZone,
date: dateB,
body: .moon,
longitude: -73.935242,
latitude: 40.730610,
altitude: 0)
XCTAssertEqual(moonRiseNYC.date?.description, "2021-03-15 08:25:55 +0000")
}
func testPlanetRisingTime() throws {
let timestamp = "2021-03-14"
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(identifier: "America/Los_Angeles")
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = try XCTUnwrap(dateFormatter.date(from: timestamp))
let sunriseSantaCruz = RiseTime<Planet>(date: date,
body: .sun,
longitude: -122.0297222,
latitude: 36.9741667,
altitude: 0)
XCTAssertEqual(sunriseSantaCruz.date?.description, "2021-03-14 14:19:44 +0000")
let dateB = try XCTUnwrap(dateFormatter.date(from: "2021-03-15"))
let moonRiseNYC = RiseTime<Planet>(date: dateB,
body: .moon,
longitude: -73.935242,
latitude: 40.730610,
altitude: 0)
XCTAssertEqual(moonRiseNYC.date?.description, "2021-03-15 12:25:55 +0000")
}
func testPlanetSettingTime() throws {
let timestamp = "2021-03-15"
let timestamp = "2021-03-15"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = try XCTUnwrap(dateFormatter.date(from: timestamp))
let timeZone = try XCTUnwrap(TimeZone(abbreviation: "CEST"))
let moonSet = SetTime<Planet>(timeZone: timeZone,
date: date,
body: .moon,
longitude: 13.41053,
latitude: 52.52437)
XCTAssertEqual(moonSet.date?.description, "2021-03-15 21:25:58 +0000")
let dateB = try XCTUnwrap(dateFormatter.date(from: "2021-03-16"))
let tokyoTimeZone = try XCTUnwrap(TimeZone(identifier: "Asia/Tokyo"))
let sunsetTokyo = SetTime<Planet>(timeZone: tokyoTimeZone,
date: dateB,
let date = try XCTUnwrap(dateFormatter.date(from: timestamp))
let moonSet = SetTime<Planet>(date: date,
body: .moon,
longitude: 13.41053,
latitude: 52.52437)
XCTAssertEqual(moonSet.date?.description, "2021-03-15 19:25:58 +0000")
let dateB = try XCTUnwrap(dateFormatter.date(from: "2021-03-16"))
let sunsetTokyo = SetTime<Planet>(date: dateB,
body: .sun,
longitude: 139.69171,
latitude: 35.6895)
XCTAssertEqual(sunsetTokyo.date?.description, "2021-03-16 17:49:34 +0000")
XCTAssertEqual(sunsetTokyo.date?.description, "2021-03-16 08:49:34 +0000")
}
func testLunarPhase() throws {

View File

@ -17,7 +17,6 @@ final class PerformanceTests: XCTestCase {
for day in 0...1065 {
Planet.allCases.forEach {
XCTAssertNotNil(Coordinate<Planet>(body: $0, date: date))
print("x")
if #available(iOS 13.0, *) {
date = date.advanced(by: (60 * 60 * 24) * TimeInterval(day))
}
@ -131,15 +130,6 @@ final class PerformanceTests: XCTestCase {
}
}
}
func testBatchRequestLunations() {
let lunationsRequest = LunationsRequest()
measure {
lunationsRequest.fetch(start: date, end: date.addingTimeInterval(60 * 60 * 24 * 30), interval: 60 * 60) {
XCTAssertEqual($0.count, 720)
}
}
}
static var allTests = [
("testCoordinatePerformance",testCoordinatePerformance,
@ -150,7 +140,6 @@ final class PerformanceTests: XCTestCase {
"testAspectPerformance", testAspectPerformance,
"testSpringEquinoxDatePerformance", testSpringEquinoxDatePerformance,
"testAutumnalEquinoxDatePerformance", testAutumnalEquinoxDatePerformance,
"testBatchRequestPlanetCoordinates", testBatchRequestPlanetCoordinates,
"testBatchRequestLunations", testBatchRequestLunations)
"testBatchRequestPlanetCoordinates", testBatchRequestPlanetCoordinates)
]
}