Releases: mannylopez/TinyMoon
[3.0.1] Add timezone to fullMoonName computed property
What's Changed
Bug fix
- Add timezone to fullMoonName computed property by @mannylopez in #43
Full Changelog: 3.0.0...3.0.1
[3.0.0] Add more metadata to Moon and ExactMoon. Update to API.
Breaking change
If your app uses the Moon.moonDetail
property to access any of the following properties
public struct MoonDetail: Hashable {
public let julianDay: Double
/// Number of days elapsed into the synodic cycle, represented as a fraction
public let daysElapsedInCycle: Double
/// Age of the moon in days, minutes, hours
public let ageOfMoon: (days: Int, hours: Int, minutes: Int)
/// Illuminated portion of the Moon, where 0.0 = new and 0.99 = full
public let illuminatedFraction: Double
/// Distance of moon from the center of the Earth, in kilometers
public let distanceFromCenterOfEarth: Double
/// Phase of the Moon, represented as a fraction
///
/// Varies between `0.0` to `0.99`.
/// `0.0` new moon,
/// `0.25` first quarter,
/// `0.5` full moon,
/// `0.75` last quarter
public let phase: Double
}
these properties can now be accessed directly via Moon
public struct Moon: Hashable {
init() {...}
// MARK: Public
/// Represents where the phase is in the current synodic cycle. Varies between `0.0` to `0.99`.
///
/// `0.0` new moon, `0.25` first quarter, `0.5` full moon, `0.75` last
public let phaseFraction: Double
/// Illuminated fraction of Moon's disk, between `0.0` and `1.0`.
///
/// `0` indicates a new moon and `1.0` indicates a full moon.
public let illuminatedFraction: Double
public let moonPhase: MoonPhase
public let name: String
public let emoji: String
public let date: Date
/// Returns `0` if the current `date` is a full moon
public var daysTillFullMoon: Int
/// Returns `0` if the current `date` is a new moon
public var daysTillNewMoon: Int
public var moonDetail: TinyMoon.MoonDetail
public var fullMoonName: String? {
if isFullMoon() {
let calendar = Calendar.current
let components = calendar.dateComponents([.month], from: date)
if let month = components.month {
return fullMoonName(month: month)
}
}
return nil
}
public func isFullMoon() -> Bool {
switch moonPhase {
case .fullMoon: true
default: false
}
}
}
What's Changed
- Refactor ExactMoon by @mannylopez in #40
- Moon: Refactor to include MoonDetail properties directly in Moon by @mannylopez in #41
Full Changelog: 2.4.1...3.0.0
[2.4.1] Create TimeTestHelper and move timezone and Date helpers there
What's Changed
- Move time date and timezone helpers to TimeTestHelper by @mannylopez in #37
Full Changelog: 2.4.0...2.4.1
[2.4.0] Add MoonDetail to public API
MoonDetail includes much more granular properties for the moon at a given time. The plan is to expose these in the public API soon, but for now, they can be accessed through the public API via MoonDetail
.
public struct MoonDetail: Hashable {
public let julianDay: Double
/// Number of days elapsed into the synodic cycle, represented as a fraction
public let daysElapsedInCycle: Double
/// Age of the moon in days, minutes, hours
public let ageOfMoon: (days: Int, hours: Int, minutes: Int)
/// Illuminated portion of the Moon, where 0.0 = new and 0.99 = full
public let illuminatedFraction: Double
/// Distance of moon from the center of the Earth, in kilometers
public let distanceFromCenterOfEarth: Double
/// Phase of the Moon, represented as a fraction
///
/// Varies between `0.0` to `0.99`.
/// `0.0` new moon,
/// `0.25` first quarter,
/// `0.5` full moon,
/// `0.75` last quarter
public let phase: Double
}
[2.3.0] Accurate phase (MoonTool)
What's Changed
TinyMoon is now a lot more accurate. SunCalc has known issues in it's Moon calculations. In my tests, I discovered two bugs
1//
The phase
value "jumped" around the full moon. This happened when the angle switched from positive to negative and the ternary operator caused a non linear jump, when phase
should be gradual.
// https://github.com/mourner/suncalc/blob/master/suncalc.js#L245
phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI,
This is what I mean by "jump" and not gradual:
...
phase = 0.47
phase = 0.48
phase = 0.51
phase = 0.50
phase = 0.49
...
2//
Also noticed that moon phases are off by about 4.5hrs. Documented here: #27
Solution
I found the excellent MoonTool program, https://www.fourmilab.ch/moontoolw/, that allowed me to download the source code. I converted the C code to Swift and removed the non-relevant parts. I then replaced phase
calculations to use the new MoonTool-based method and all tests passed.
I removed most of SunCalc's formulas.
Changelog
- Revisit astronomical constant by @mannylopez in #32
- Simplify Julian Day method by @mannylopez in #33
- Adopt MoonTool formula for calculating moon phase by @mannylopez in #34
Full Changelog: 2.2.0...2.3.0
[2.2.0] TimeZone support
What's Changed
- Update readme by @mannylopez in #23
- Organize code with swift lint by @mannylopez in #24
- Add timezone support by @mannylopez in #26
Full Changelog: 2.1.0...2.2.0
[2.1.0] Update moon calculations under the hood
What's Changed
- Nest Moon and MoonPhase objects under TinyMoon namespace by @mannylopez in #12
- Add pretty print methods to help debug by @mannylopez in #14
- Refactor julian day by @mannylopez in #16
- Add UTC tests for main moon phases by @mannylopez in #17
- Add astronomical calculations by @mannylopez in #18
- Add tests for degreesToRadians and radiansToDegrees by @mannylopez in #19
- Add AstronomicalConstant to TinyMoon + Move files around by @mannylopez in #22
Full Changelog: 2.0.0...2.1.0
[2.0.0] Refactor TinyMoon to act as namespace
Breaking change This is a major release, will update version to 2.0.0
TinyMoon namespace
Main change is that instead of having to instantiate TinyMoon, like this
let moon = TinyMoon().calculateMoonPhase()
Now the API is simpler and TinyMoon acts as a namespace, like this
let moon = TinyMoon.calculateMoonPhase()
Simplify Moon
I've also moved the logic of instantiating the Moon
object into the Moon
initializer, so instead of this
public struct Moon: Hashable {
init(moonPhase: MoonPhase, lunarDay: Double, maxLunarDay: Double, date: Date) {...}
...
}
The Moon
initializer now looks like this
public struct Moon: Hashable {
init(date: Date) {...}
...
}
This will make it easier to test the functions inside of Moon
To update
// Replace the following
TinyMoon().calculateMoonPhase()
// with
TinyMoon.calculateMoonPhase()
[1.2.0] Add daysTillNewMoon property
Adds a new property, daysTillNewMoon
, to the TinyMoon API.
Usage
let moon = TinyMoon().calculateMoonPhase(Date())
print(moon.daysTillNewMoon) // prints number of days till new moon
Will return 0
if the date given is a new moon
[1.1.0] Make Moon properties public
Full Changelog: main@{1day}...main
Makes the following properties public on Moon
object:
lunarDay
date
isFullMoon