Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AstronomicalConstant] Calculations off by ~4.5hrs #27

Closed
mannylopez opened this issue Jun 29, 2024 · 3 comments · Fixed by #34
Closed

[AstronomicalConstant] Calculations off by ~4.5hrs #27

mannylopez opened this issue Jun 29, 2024 · 3 comments · Fixed by #34
Assignees

Comments

@mannylopez
Copy link
Owner

Looks like the major moon phases have a ~4.5hr margin of error around midnight.

The following notes show what the lib/TinyMoon package show as the major moon phase, and the pst and utc columns show what timeanddate.com show for the actual moon phase.

IMG_4219

I was using this to test

func test_debug() {
    let pacificTimeZone = TinyMoon.TimeZoneOption.createTimeZone(timeZone: .pacific)
    let utcTimeZone = TinyMoon.TimeZoneOption.createTimeZone(timeZone: .utc)

//    let month = MonthTestHelper.Month.february
//
//    MoonTestHelper.prettyPrintMoonCalendar(month: month, year: 2024, timeZone: pacificTimeZone)
//    MoonTestHelper.prettyPrintMoonCalendar(month: month, year: 2024, timeZone: utcTimeZone)

    let datePacific = TinyMoon.formatDate(year: 2024, month: 02, day: 23, timeZone: pacificTimeZone)
    let dateUTC = TinyMoon.formatDate(year: 2024, month: 02, day: 23, timeZone: utcTimeZone)

    let moonPacific = TinyMoon.calculateMoonPhase(datePacific, timeZone: pacificTimeZone)
    let moonUTC = TinyMoon.calculateMoonPhase(dateUTC, timeZone: utcTimeZone)
    MoonTestHelper.prettyPrintMoonObject(moonPacific)
    MoonTestHelper.prettyPrintMoonObject(moonUTC)
  }

To debug:

@mannylopez mannylopez self-assigned this Jun 29, 2024
@mannylopez
Copy link
Owner Author

Notes

static func _getmoonPhase(phase1: Double, phase2: Double) -> Int {
      let percentages = [0, 0.25, 0.5, 0.75, 1]
      var index = 0

      if phase1 <= phase2 {
        for i in 0...percentages.count {
          if percentages[i] >= phase1, percentages[i] <= phase2 {
            index = 2 * i
            break
          } else if percentages[i] > phase1 {
            index = (2 * i) - 1
            break
          }
        }
      } else {
        index = 0
      }

      return index % 8
    }

and to test

let phases: [TinyMoon.MoonPhase] = [.newMoon, .waxingCrescent, .firstQuarter, .waxingGibbous, .fullMoon, .waningGibbous, .lastQuarter, .waningCrescent]

    let date1 = TinyMoon.formatDate(year: 2024, month: 7, day: 20, timeZone: utcTimeZone)
    let date2 = TinyMoon.formatDate(year: 2024, month: 07, day: 21, timeZone: utcTimeZone)
    let date3 = TinyMoon.formatDate(year: 2024, month: 07, day: 22, timeZone: utcTimeZone)

    let (start, end) = TinyMoon.Moon.julianStartAndEndOfDay(date: date2, timeZone: utcTimeZone)

    let p1 = TinyMoon.AstronomicalConstant.getMoonPhase(julianDay: start).phase
    let p2 = TinyMoon.AstronomicalConstant.getMoonPhase(julianDay: end).phase

    print("p1", p1)
    print("p2", p2)
    let index = TinyMoon.AstronomicalConstant._getmoonPhase(phase1: p1, phase2: p2)
    print(index)
    print(phases[index])
    ```

@mannylopez
Copy link
Owner Author

Ended up finding MoonTool and converting the source code from Visual C to Swift. Much more accurate.

@mannylopez
Copy link
Owner Author

mannylopez commented Jul 13, 2024

Tests for these cases added here:

// These following moon phases happen within 5 hours of midnight, so these tests aim to check that the phase is calculated correctly and lands on the correct day
func test_moon_marginOfError() {
// 4 full moon (3 PST / 1 UTC)
// 5 new moon (4 PST / 1 UTC)
// 1 last quarter (1 UTC)
// --------------
// 10 total (7 PST / 3 UTC)
// MARK: - PST margin of error tests
// Values from https://www.timeanddate.com/moon/phases/usa/portland-or
// Full moon on 2/24/2024 @ 04:30 PST
var date = TinyMoon.formatDate(year: 2024, month: 2, day: 24, hour: 4, minute: 30, timeZone: pacificTimeZone)
var moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .fullMoon)
// New moon on 3/10/2024 @ 01:00 PST
date = TinyMoon.formatDate(year: 2024, month: 3, day: 10, hour: 1, minute: 0, timeZone: pacificTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .newMoon)
// Full moon on 3/25/2024 @ 00:00 PST
date = TinyMoon.formatDate(year: 2024, month: 3, day: 25, hour: 0, minute: 0, timeZone: pacificTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .fullMoon)
// New moon on 3/10/2024 @ 01:00 PST
date = TinyMoon.formatDate(year: 2024, month: 3, day: 10, hour: 1, minute: 0, timeZone: pacificTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .newMoon)
// New moon on 8/4/2024 @ 04:13 PST
date = TinyMoon.formatDate(year: 2024, month: 8, day: 4, hour: 4, minute: 13, timeZone: pacificTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .newMoon)
// New moon on 11/30/2024 @ 22:21 PST
date = TinyMoon.formatDate(year: 2024, month: 11, day: 30, hour: 22, minute: 21, timeZone: pacificTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .newMoon)
// Full moon on 12/15/2024 @ 01:01 PST
date = TinyMoon.formatDate(year: 2024, month: 12, day: 15, hour: 1, minute: 01, timeZone: pacificTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: pacificTimeZone)
XCTAssertEqual(moon.moonPhase, .fullMoon)
// MARK: - UTC margin of error tests
// Values from https://www.timeanddate.com/moon/phases/timezone/utc
// Last Quarter moon on 4/2/2024 @ 03:14 UTC
date = TinyMoon.formatDate(year: 2024, month: 4, day: 2, hour: 3, minute: 14, timeZone: utcTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: utcTimeZone)
XCTAssertEqual(moon.moonPhase, .lastQuarter)
// Full moon on 4/23/2024 @ 23:48 UTC
date = TinyMoon.formatDate(year: 2024, month: 4, day: 23, hour: 23, minute: 48, timeZone: utcTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: utcTimeZone)
XCTAssertEqual(moon.moonPhase, .fullMoon)
// New moon on 9/3/2024 @ 01:55 UTC
date = TinyMoon.formatDate(year: 2024, month: 9, day: 3, hour: 1, minute: 55, timeZone: utcTimeZone)
moon = TinyMoon.calculateMoonPhase(date, timeZone: utcTimeZone)
XCTAssertEqual(moon.moonPhase, .newMoon)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant