From 815eec783f5de88d831b50010a627ae44877a022 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 17:26:25 -0600 Subject: [PATCH 01/45] Refactor common portions of conversion algorithms --- .../ArmenianCalendar+JDN.swift | 99 +++++------------ .../JulianDayNumber/CopticCalendar+JDN.swift | 101 +++++------------ .../EgyptianCalendar+JDN.swift | 101 +++++------------ .../EthiopianCalendar+JDN.swift | 101 +++++------------ .../JulianDayNumber/IslamicCalendar+JDN.swift | 103 +++++------------- Sources/JulianDayNumber/JDN.swift | 76 +++++++++++++ .../JulianDayNumber/JulianCalendar+JDN.swift | 101 +++++------------ .../KhwarizmianCalendar+JDN.swift | 99 +++++------------ 8 files changed, 266 insertions(+), 515 deletions(-) diff --git a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift index 809428f..d081dcb 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift @@ -6,79 +6,34 @@ import Foundation -/// The number of years in a cycle of the Armenian calendar. -/// -/// A cycle in the Armenian calendar consists of 1 year. -let armenianCalendarCycleYears = 1 - -/// The number of days in a cycle of the Armenian calendar. -/// -/// A cycle in the Armenian calendar consists of 1 year of 365 days. -let armenianCalendarCycleDays = 365 - -extension ArmenianCalendar: JulianDayNumberConverting { +extension ArmenianCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Armenian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -5268-11-18 in the proleptic Armenian calendar. - if date < (-5268, 11, 18) { - ΔcalendarCycles = (-5269 - Y) / armenianCalendarCycleYears + 1 - Y += ΔcalendarCycles * armenianCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * armenianCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / armenianCalendarCycleDays + 1 - J += ΔcalendarCycles * armenianCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * armenianCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Armenian calendar. + /// + /// A cycle in the Armenian calendar consists of 1 year. + static let calendarCycleYears = 1 + + /// The number of days in a cycle of the Armenian calendar. + /// + /// A cycle in the Armenian calendar consists of 1 year of 365 days. + static let calendarCycleDays = 365 + + /// The date for Julian day number zero in the proleptic Armenian calendar + static let julianDayNumberZero = (year: -5268, month: 11, day: 18) + + // Constants for Armenian calendar conversions + static let y = 5268 + static let j = 317 + static let m = 0 + static let n = 13 + static let r = 1 + static let p = 365 + static let q = 0 + static let v = 0 + static let u = 1 + static let s = 30 + static let t = 0 + static let w = 0 } - -// Constants for Armenian calendar conversions -private let y = 5268 -private let j = 317 -private let m = 0 -private let n = 13 -private let r = 1 -private let p = 365 -private let q = 0 -private let v = 0 -private let u = 1 -private let s = 30 -private let t = 0 -private let w = 0 diff --git a/Sources/JulianDayNumber/CopticCalendar+JDN.swift b/Sources/JulianDayNumber/CopticCalendar+JDN.swift index 3c27e18..db43e9a 100644 --- a/Sources/JulianDayNumber/CopticCalendar+JDN.swift +++ b/Sources/JulianDayNumber/CopticCalendar+JDN.swift @@ -6,81 +6,34 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Coptic calendar. -/// -/// A cycle in the Coptic calendar consists of 3 common years and 1 leap year. -let copticCalendarCycleYears = 4 - -/// The number of days in a cycle of the Coptic calendar. -/// -/// A cycle in the Coptic calendar consists of 3 years of 365 days and 1 leap year of 366 days. -let copticCalendarCycleDays = 1461 - -extension CopticCalendar: JulianDayNumberConverting { +extension CopticCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Coptic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -4996-05-05 in the proleptic Coptic calendar. - if date < (-4996, 5, 5) { - ΔcalendarCycles = (-4997 - Y) / copticCalendarCycleYears + 1 - Y += ΔcalendarCycles * copticCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * copticCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / copticCalendarCycleDays + 1 - J += ΔcalendarCycles * copticCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * copticCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Coptic calendar. + /// + /// A cycle in the Coptic calendar consists of 3 common years and 1 leap year. + static let calendarCycleYears = 4 + + /// The number of days in a cycle of the Coptic calendar. + /// + /// A cycle in the Coptic calendar consists of 3 years of 365 days and 1 leap year of 366 days. + static let calendarCycleDays = 1461 + + /// The date for Julian day number zero in the Coptic Julian calendar + static let julianDayNumberZero = (year: -4996, month: 5, day: 5) + + // Constants for Coptic calendar conversions + static let y = 4996 + static let j = 124 + static let m = 0 + static let n = 13 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 1 + static let s = 30 + static let t = 0 + static let w = 0 } - -// Constants for Coptic calendar conversions -private let y = 4996 -private let j = 124 -private let m = 0 -private let n = 13 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 1 -private let s = 30 -private let t = 0 -private let w = 0 diff --git a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift index ec6faa0..706fd9c 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift @@ -6,81 +6,34 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Egyptian calendar. -/// -/// A cycle in the Egyptian calendar consists of 1 year. -let egyptianCalendarCycleYears = 1 - -/// The number of days in a cycle of the Egyptian calendar. -/// -/// A cycle in the Egyptian calendar consists of 1 year of 365 days. -let egyptianCalendarCycleDays = 365 - -extension EgyptianCalendar: JulianDayNumberConverting { +extension EgyptianCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Egyptian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -3968-02-18 in the proleptic Egyptian calendar. - if date < (-3968, 2, 18) { - ΔcalendarCycles = (-3969 - Y) / egyptianCalendarCycleYears + 1 - Y += ΔcalendarCycles * egyptianCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * egyptianCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / egyptianCalendarCycleDays + 1 - J += ΔcalendarCycles * egyptianCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * egyptianCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Egyptian calendar. + /// + /// A cycle in the Egyptian calendar consists of 1 year. + static let calendarCycleYears = 1 + + /// The number of days in a cycle of the Egyptian calendar. + /// + /// A cycle in the Egyptian calendar consists of 1 year of 365 days. + static let calendarCycleDays = 365 + + /// The date for Julian day number zero in the proleptic Egyptian calendar + static let julianDayNumberZero = (year: -3968, month: 2, day: 2) + + // Constants for Egyptian calendar conversions + static let y = 3968 + static let j = 47 + static let m = 0 + static let n = 13 + static let r = 1 + static let p = 365 + static let q = 0 + static let v = 0 + static let u = 1 + static let s = 30 + static let t = 0 + static let w = 0 } - -// Constants for Egyptian calendar conversions -private let y = 3968 -private let j = 47 -private let m = 0 -private let n = 13 -private let r = 1 -private let p = 365 -private let q = 0 -private let v = 0 -private let u = 1 -private let s = 30 -private let t = 0 -private let w = 0 diff --git a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift index e1ab099..6ef43c4 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift @@ -6,81 +6,34 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Ethiopian calendar. -/// -/// A cycle in the Ethiopian calendar consists of 3 common years and 1 leap year. -let ethiopianCalendarCycleYears = 4 - -/// The number of days in a cycle of the Ethiopian calendar. -/// -/// A cycle in the Ethiopian calendar consists of 3 years of 365 days and 1 leap year of 366 days. -let ethiopianCalendarCycleDays = 1461 - -extension EthiopianCalendar: JulianDayNumberConverting { +extension EthiopianCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Ethiopian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -4720-05-05 in the proleptic Ethiopian calendar. - if date < (-4720, 5, 5) { - ΔcalendarCycles = (-4721 - Y) / ethiopianCalendarCycleYears + 1 - Y += ΔcalendarCycles * ethiopianCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * ethiopianCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / ethiopianCalendarCycleDays + 1 - J += ΔcalendarCycles * ethiopianCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * ethiopianCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Ethiopian calendar. + /// + /// A cycle in the Ethiopian calendar consists of 3 common years and 1 leap year. + static let calendarCycleYears = 4 + + /// The number of days in a cycle of the Ethiopian calendar. + /// + /// A cycle in the Ethiopian calendar consists of 3 years of 365 days and 1 leap year of 366 days. + static let calendarCycleDays = 1461 + + /// The date for Julian day number zero in the proleptic Ethiopian calendar + static let julianDayNumberZero = (year: -4720, month: 5, day: 5) + + // Constants for Ethiopian calendar conversions + static let y = 4720 + static let j = 124 + static let m = 0 + static let n = 13 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 1 + static let s = 30 + static let t = 0 + static let w = 0 } - -// Constants for Ethiopian calendar conversions -private let y = 4720 -private let j = 124 -private let m = 0 -private let n = 13 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 1 -private let s = 30 -private let t = 0 -private let w = 0 diff --git a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift index 6c1226e..8892d4a 100644 --- a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift +++ b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift @@ -6,82 +6,35 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Islamic calendar. -/// -/// A cycle in the Islamic calendar consists of 19 common years and 11 leap years. -let islamicCalendarCycleYears = 30 - -/// The number of days in a cycle of the Islamic calendar. -/// -/// A cycle in the Islamic calendar consists of 19 years of 354 days and 11 leap years of 355 days. -let islamicCalendarCycleDays = 10631 - -extension IslamicCalendar: JulianDayNumberConverting { +extension IslamicCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Islamic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -5498-08-16 in the proleptic Islamic calendar. - if date < (-5498, 8, 16) { - ΔcalendarCycles = (-5498 - Y) / islamicCalendarCycleYears + 1 - Y += ΔcalendarCycles * islamicCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * islamicCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / islamicCalendarCycleDays + 1 - J += ΔcalendarCycles * islamicCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * islamicCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Islamic calendar. + /// + /// A cycle in the Islamic calendar consists of 19 common years and 11 leap years. + static let calendarCycleYears = 30 + + /// The number of days in a cycle of the Islamic calendar. + /// + /// A cycle in the Islamic calendar consists of 19 years of 354 days and 11 leap years of 355 days. + static let calendarCycleDays = 10631 + + /// The date for Julian day number zero in the proleptic Julian calendar + static let julianDayNumberZero = (year: -5498, month: 8, day: 16) + + // Constants for Islamic calendar conversions + static let y = 5519 + static let j = 7664 + // Islamic A is identical except j = 7665 + static let m = 0 + static let n = 12 + static let r = 30 + static let p = 10631 + static let q = 14 + static let v = 15 + static let u = 100 + static let s = 2951 + static let t = 51 + static let w = 10 } - -// Constants for Islamic calendar conversions -private let y = 5519 -private let j = 7664 -// Islamic A is identical except j = 7665 -private let m = 0 -private let n = 12 -private let r = 30 -private let p = 10631 -private let q = 14 -private let v = 15 -private let u = 100 -private let s = 2951 -private let t = 51 -private let w = 10 diff --git a/Sources/JulianDayNumber/JDN.swift b/Sources/JulianDayNumber/JDN.swift index 92d1964..086b775 100644 --- a/Sources/JulianDayNumber/JDN.swift +++ b/Sources/JulianDayNumber/JDN.swift @@ -52,3 +52,79 @@ extension JulianDayNumberConverting where DateType == (year: Int, month: Int, da julianDayNumberFromDate((Y, M, D)) } } + +// MARK: - Conversion Algorithms + +// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. + +protocol YearMonthDayJulianDayNumberConverting: JulianDayNumberConverting where DateType == (year: Int, month: Int, day: Int) { + static var calendarCycleDays: Int { get } + static var calendarCycleYears: Int { get } + static var julianDayNumberZero: DateType { get } + + static var y: Int { get } + static var j: Int { get } + static var m: Int { get } + static var n: Int { get } + static var r: Int { get } + static var p: Int { get } + static var q: Int { get } + static var v: Int { get } + static var u: Int { get } + static var s: Int { get } + static var t: Int { get } + static var w: Int { get } +} + +extension YearMonthDayJulianDayNumberConverting { + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if date < julianDayNumberZero { + ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / calendarCycleYears + 1 + Y += ΔcalendarCycles * calendarCycleYears + } + + let h = date.month - m + let g = Y + y - (n - h) / n + let f = (h - 1 + n) % n + let e = (p * g + q) / r + date.day - 1 - j + var J = e + (s * f + t) / u + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * calendarCycleDays + } + + return J + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { +// precondition(J < Int.max - 1) + + var J = J + var ΔcalendarCycles = 0 + + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / calendarCycleDays + 1 + J += ΔcalendarCycles * calendarCycleDays + } + + precondition(J <= Int.max - j, "Julian day number too large") + + let f = J + j + let e = r * f + v + let g = (e % p) / r + let h = u * g + w + let D = (h % s) / u + 1 + let M = ((h / s + m) % n) + 1 + var Y = e / p - y + (n + m - M) / n + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * calendarCycleYears + } + + return (Y, M, D) + } +} diff --git a/Sources/JulianDayNumber/JulianCalendar+JDN.swift b/Sources/JulianDayNumber/JulianCalendar+JDN.swift index ac66b41..56fa7c5 100644 --- a/Sources/JulianDayNumber/JulianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/JulianCalendar+JDN.swift @@ -6,81 +6,34 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Julian calendar. -/// -/// A cycle in the Julian calendar consists of 3 common years and 1 leap year. -let julianCalendarCycleYears = 4 - -/// The number of days in a cycle of the Julian calendar. -/// -/// A cycle in the Julian calendar consists of 3 years of 365 days and 1 leap year of 366 days. -let julianCalendarCycleDays = 1461 - -extension JulianCalendar: JulianDayNumberConverting { +extension JulianCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Julian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -4712-01-01 in the proleptic Julian calendar. - if Y < -4712 { - ΔcalendarCycles = (-4713 - Y) / julianCalendarCycleYears + 1 - Y += ΔcalendarCycles * julianCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * julianCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / julianCalendarCycleDays + 1 - J += ΔcalendarCycles * julianCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * julianCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Julian calendar. + /// + /// A cycle in the Julian calendar consists of 3 common years and 1 leap year. + static let calendarCycleYears = 4 + + /// The number of days in a cycle of the Julian calendar. + /// + /// A cycle in the Julian calendar consists of 3 years of 365 days and 1 leap year of 366 days. + static let calendarCycleDays = 1461 + + /// The date for Julian day number zero in the proleptic Julian calendar + static let julianDayNumberZero = (year: -4712, month: 1, day: 1) + + // Constants for Julian calendar conversions + static let y = 4716 + static let j = 1401 + static let m = 2 + static let n = 12 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 5 + static let s = 153 + static let t = 2 + static let w = 2 } - -// Constants for Julian calendar conversions -private let y = 4716 -private let j = 1401 -private let m = 2 -private let n = 12 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 5 -private let s = 153 -private let t = 2 -private let w = 2 diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift index a8c148f..282fc83 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift @@ -6,79 +6,34 @@ import Foundation -/// The number of years in a cycle of the Khwarizmian calendar. -/// -/// A cycle in the Khwarizmian calendar consists of 1 year. -let khwarizmianCalendarCycleYears = 1 - -/// The number of days in a cycle of the Khwarizmian calendar. -/// -/// A cycle in the Khwarizmian calendar consists of 1 year of 365 days. -let khwarizmianCalendarCycleDays = 365 - -extension KhwarizmianCalendar: JulianDayNumberConverting { +extension KhwarizmianCalendar: YearMonthDayJulianDayNumberConverting { /// A date in the Khwarizmian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -5348-11-18 in the proleptic Khwarizmian calendar. - if date < (-5348, 11, 18) { - ΔcalendarCycles = (-5349 - Y) / khwarizmianCalendarCycleYears + 1 - Y += ΔcalendarCycles * khwarizmianCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * khwarizmianCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / khwarizmianCalendarCycleDays + 1 - J += ΔcalendarCycles * khwarizmianCalendarCycleDays - } - - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * khwarizmianCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Khwarizmian calendar. + /// + /// A cycle in the Khwarizmian calendar consists of 1 year. + static let calendarCycleYears = 1 + + /// The number of days in a cycle of the Khwarizmian calendar. + /// + /// A cycle in the Khwarizmian calendar consists of 1 year of 365 days. + static let calendarCycleDays = 365 + + /// The date for Julian day number zero in the proleptic Julian calendar + static let julianDayNumberZero = (year: -5348, month: 11, day: 18) + + // Constants for Khwarizmian calendar conversions + static let y = 5348 + static let j = 317 + static let m = 0 + static let n = 13 + static let r = 1 + static let p = 365 + static let q = 0 + static let v = 0 + static let u = 1 + static let s = 30 + static let t = 0 + static let w = 0 } - -// Constants for Khwarizmian calendar conversions -private let y = 5348 -private let j = 317 -private let m = 0 -private let n = 13 -private let r = 1 -private let p = 365 -private let q = 0 -private let v = 0 -private let u = 1 -private let s = 30 -private let t = 0 -private let w = 0 From a3f1c00b7dbcc856adbeda377cd732751725e5c2 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 18:35:32 -0600 Subject: [PATCH 02/45] Refactor Gregorian-type intercalation --- .../JulianDayNumber/BahaiCalendar+JDN.swift | 109 +++++------------- .../FrenchRepublicanCalendar+JDN.swift | 109 +++++------------- .../GregorianCalendar+JDN.swift | 109 +++++------------- Sources/JulianDayNumber/JDN.swift | 78 +++++++++++++ .../JulianDayNumber/SakaCalendar+JDN.swift | 71 ++++++------ 5 files changed, 205 insertions(+), 271 deletions(-) diff --git a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift index f03cb69..12dd8dc 100644 --- a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift +++ b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift @@ -6,86 +6,37 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Baháʼí calendar. -/// -/// A cycle in the Baháʼí calendar consists of 303 common years and 97 leap years. -let bahaiCalendarCycleYears = 400 - -/// The number of days in a cycle of the Baháʼí calendar. -/// -/// A cycle in the Baháʼí calendar consists of 303 years of 365 days and 97 leap year of 366 days. -let bahaiCalendarCycleDays = 146097 - -extension BahaiCalendar: JulianDayNumberConverting { +extension BahaiCalendar: GregorianIntercalatingJulianDayNumberConverting { /// A date in the Baháʼí calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -6556-14-02 in the proleptic Baháʼí calendar. - if date < (-6556, 14, 2) { - ΔcalendarCycles = (-6557 - Y) / bahaiCalendarCycleYears + 1 - Y += ΔcalendarCycles * bahaiCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - J = J - (3 * ((g + A) / 100)) / 4 - C - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * bahaiCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / bahaiCalendarCycleDays + 1 - J += ΔcalendarCycles * bahaiCalendarCycleDays - } - - var f = J + j - f = f + (((4 * J + B) / 146097) * 3) / 4 + C - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * bahaiCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Baháʼí calendar. + /// + /// A cycle in the Baháʼí calendar consists of 303 common years and 97 leap years. + static let calendarCycleYears = 400 + + /// The number of days in a cycle of the Baháʼí calendar. + /// + /// A cycle in the Baháʼí calendar consists of 303 years of 365 days and 97 leap year of 366 days. + static let calendarCycleDays = 146097 + + /// The date for Julian day number zero in the Baháʼí Gregorian calendar + static let julianDayNumberZero = (year: -6556, month: 14, day: 2) + + // Constants for Baháʼí calendar conversions + static let y = 6560 + static let j = 1412 + static let m = 19 + static let n = 20 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 1 + static let s = 19 + static let t = 0 + static let w = 0 + static let A = 184 + static let B = 274273 + static let C = -50 } - -// Constants for Baháʼí calendar conversions -private let y = 6560 -private let j = 1412 -private let m = 19 -private let n = 20 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 1 -private let s = 19 -private let t = 0 -private let w = 0 -private let A = 184 -private let B = 274273 -private let C = -50 diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift index 6f63ac3..7e57bad 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift @@ -6,86 +6,37 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the French Republican calendar. -/// -/// A cycle in the modified French Republican calendar consists of 303 common years and 97 leap years. -let frenchRepublicanCalendarCycleYears = 400 - -/// The number of days in a cycle of the French Republican calendar. -/// -/// A cycle in the modified French Republican calendar consists of 303 years of 365 days and 97 leap year of 366 days. -let frenchRepublicanCalendarCycleDays = 146097 - -extension FrenchRepublicanCalendar: JulianDayNumberConverting { +extension FrenchRepublicanCalendar: GregorianIntercalatingJulianDayNumberConverting { /// A date in the French Republican calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -6504-03-03 in the proleptic French Republican calendar. - if date < (-6504, 3, 3) { - ΔcalendarCycles = (-6505 - Y) / frenchRepublicanCalendarCycleYears + 1 - Y += ΔcalendarCycles * frenchRepublicanCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - J = J - (3 * ((g + A) / 100)) / 4 - C - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * frenchRepublicanCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / frenchRepublicanCalendarCycleDays + 1 - J += ΔcalendarCycles * frenchRepublicanCalendarCycleDays - } - - var f = J + j - f = f + (((4 * J + B) / 146097) * 3) / 4 + C - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * frenchRepublicanCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the French Republican calendar. + /// + /// A cycle in the modified French Republican calendar consists of 303 common years and 97 leap years. + static let calendarCycleYears = 400 + + /// The number of days in a cycle of the French Republican calendar. + /// + /// A cycle in the modified French Republican calendar consists of 303 years of 365 days and 97 leap year of 366 days. + static let calendarCycleDays = 146097 + + /// The date for Julian day number zero in the proleptic French Republican calendar + static let julianDayNumberZero = (year: -6504, month: 3, day: 3) + + // Constants for French Republican calendar conversions + static let y = 6504 + static let j = 111 + static let m = 0 + static let n = 13 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 1 + static let s = 30 + static let t = 0 + static let w = 0 + static let A = 396 + static let B = 578797 + static let C = -51 } - -// Constants for French Republican calendar conversions -private let y = 6504 -private let j = 111 -private let m = 0 -private let n = 13 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 1 -private let s = 30 -private let t = 0 -private let w = 0 -private let A = 396 -private let B = 578797 -private let C = -51 diff --git a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift index 33ea1eb..5489685 100644 --- a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift @@ -6,86 +6,37 @@ import Foundation -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// The number of years in a cycle of the Gregorian calendar. -/// -/// A cycle in the Gregorian calendar consists of 303 common years and 97 leap years. -let gregorianCalendarCycleYears = 400 - -/// The number of days in a cycle of the Gregorian calendar. -/// -/// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. -let gregorianCalendarCycleDays = 146097 - -extension GregorianCalendar: JulianDayNumberConverting { +extension GregorianCalendar: GregorianIntercalatingJulianDayNumberConverting { /// A date in the Gregorian calendar consists of a year, month, and day. public typealias DateType = JulianCalendar.DateType - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - // JDN 0 is -4713-11-24 in the proleptic Gregorian calendar. - if date < (-4713, 11, 24) { - ΔcalendarCycles = (-4714 - Y) / gregorianCalendarCycleYears + 1 - Y += ΔcalendarCycles * gregorianCalendarCycleYears - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - J = J - (3 * ((g + A) / 100)) / 4 - C - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * gregorianCalendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / gregorianCalendarCycleDays + 1 - J += ΔcalendarCycles * gregorianCalendarCycleDays - } - - var f = J + j - f = f + (((4 * J + B) / 146097) * 3) / 4 + C - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * gregorianCalendarCycleYears - } - - return (Y, M, D) - } + /// The number of years in a cycle of the Gregorian calendar. + /// + /// A cycle in the Gregorian calendar consists of 303 common years and 97 leap years. + static let calendarCycleYears = 400 + + /// The number of days in a cycle of the Gregorian calendar. + /// + /// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. + static let calendarCycleDays = 146097 + + /// The date for Julian day number zero in the proleptic Gregorian calendar + static let julianDayNumberZero = (year: -4713, month: 11, day: 24) + + // Constants for Gregorian calendar conversions + static let y = 4716 + static let j = 1401 + static let m = 2 + static let n = 12 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 5 + static let s = 153 + static let t = 2 + static let w = 2 + static let A = 184 + static let B = 274277 + static let C = -38 } - -// Constants for Gregorian calendar conversions -private let y = 4716 -private let j = 1401 -private let m = 2 -private let n = 12 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 5 -private let s = 153 -private let t = 2 -private let w = 2 -private let A = 184 -private let B = 274277 -private let C = -38 diff --git a/Sources/JulianDayNumber/JDN.swift b/Sources/JulianDayNumber/JDN.swift index 086b775..aef6b98 100644 --- a/Sources/JulianDayNumber/JDN.swift +++ b/Sources/JulianDayNumber/JDN.swift @@ -128,3 +128,81 @@ extension YearMonthDayJulianDayNumberConverting { return (Y, M, D) } } + +// MARK: Gregorian-type Intercalation + +protocol GregorianIntercalatingJulianDayNumberConverting: JulianDayNumberConverting where DateType == (year: Int, month: Int, day: Int) { + static var calendarCycleDays: Int { get } + static var calendarCycleYears: Int { get } + static var julianDayNumberZero: DateType { get } + + static var y: Int { get } + static var j: Int { get } + static var m: Int { get } + static var n: Int { get } + static var r: Int { get } + static var p: Int { get } + static var q: Int { get } + static var v: Int { get } + static var u: Int { get } + static var s: Int { get } + static var t: Int { get } + static var w: Int { get } + static var A: Int { get } + static var B: Int { get } + static var C: Int { get } +} + +extension GregorianIntercalatingJulianDayNumberConverting { + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if date < julianDayNumberZero { + ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / calendarCycleYears + 1 + Y += ΔcalendarCycles * calendarCycleYears + } + + let h = date.month - m + let g = Y + y - (n - h) / n + let f = (h - 1 + n) % n + let e = (p * g + q) / r + date.day - 1 - j + var J = e + (s * f + t) / u + J = J - (3 * ((g + A) / 100)) / 4 - C + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * calendarCycleDays + } + + return J + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + var J = J + var ΔcalendarCycles = 0 + + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / calendarCycleDays + 1 + J += ΔcalendarCycles * calendarCycleDays + } + + precondition(J <= Int.max - j, "Julian day number too large") + + var f = J + j + f = f + (((4 * J + B) / 146097) * 3) / 4 + C + let e = r * f + v + let g = (e % p) / r + let h = u * g + w + let D = (h % s) / u + 1 + let M = ((h / s + m) % n) + 1 + var Y = e / p - y + (n + m - M) / n + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * calendarCycleYears + } + + return (Y, M, D) + } +} + diff --git a/Sources/JulianDayNumber/SakaCalendar+JDN.swift b/Sources/JulianDayNumber/SakaCalendar+JDN.swift index e3c58ab..98c66d6 100644 --- a/Sources/JulianDayNumber/SakaCalendar+JDN.swift +++ b/Sources/JulianDayNumber/SakaCalendar+JDN.swift @@ -8,28 +8,31 @@ import Foundation // Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. -/// The number of years in a cycle of the Śaka calendar. -/// -/// A cycle in the Śaka calendar consists of 303 common years and 97 leap years. -let sakaCalendarCycleYears = 400 - -/// The number of days in a cycle of the Śaka calendar. -/// -/// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. -let sakaCalendarCycleDays = 146097 - extension SakaCalendar: JulianDayNumberConverting { /// A date in the Śaka calendar consists of a year, month, and day. public typealias DateType = (year: Int, month: Int, day: Int) + /// The number of years in a cycle of the Śaka calendar. + /// + /// A cycle in the Śaka calendar consists of 303 common years and 97 leap years. + static let calendarCycleYears = 400 + + /// The number of days in a cycle of the Śaka calendar. + /// + /// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. + static let calendarCycleDays = 146097 + + /// The date for Julian day number zero in the proleptic Śaka calendar + static let julianDayNumberZero = (year: -4791, month: 9, day: 3) + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 // JDN 0 is -4791-09-03 in the proleptic Śaka calendar. - if date < (-4791, 9, 3) { - ΔcalendarCycles = (-4792 - Y) / sakaCalendarCycleYears + 1 - Y += ΔcalendarCycles * sakaCalendarCycleYears + if date < julianDayNumberZero { + ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / calendarCycleYears + 1 + Y += ΔcalendarCycles * calendarCycleYears } let h = date.month - m @@ -41,7 +44,7 @@ extension SakaCalendar: JulianDayNumberConverting { J = J - (3 * ((g + A) / 100)) / 4 - C if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * sakaCalendarCycleDays + J -= ΔcalendarCycles * calendarCycleDays } return J @@ -53,8 +56,8 @@ extension SakaCalendar: JulianDayNumberConverting { // Richards' algorithm is only valid for positive JDNs. if J < 0 { - ΔcalendarCycles = -J / sakaCalendarCycleDays + 1 - J += ΔcalendarCycles * sakaCalendarCycleDays + ΔcalendarCycles = -J / calendarCycleDays + 1 + J += ΔcalendarCycles * calendarCycleDays } var f = J + j @@ -72,26 +75,26 @@ extension SakaCalendar: JulianDayNumberConverting { var Y = e / p - y + (n + m - M) / n if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * sakaCalendarCycleYears + Y -= ΔcalendarCycles * calendarCycleYears } return (Y, M, D) } -} -// Constants for Śaka calendar conversions -private let y = 4794 -private let j = 1348 -private let m = 1 -private let n = 12 -private let r = 4 -private let p = 1461 -private let q = 0 -private let v = 3 -private let u = 1 -private let s = 31 -private let t = 0 -private let w = 0 -private let A = 184 -private let B = 274073 -private let C = -36 + // Constants for Śaka calendar conversions + static let y = 4794 + static let j = 1348 + static let m = 1 + static let n = 12 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 1 + static let s = 31 + static let t = 0 + static let w = 0 + static let A = 184 + static let B = 274073 + static let C = -36 +} From 30bc28e15984283e82cd6ee96cc6dcece9b3d626 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 18:38:47 -0600 Subject: [PATCH 03/45] Refactor --- .../JulianDayNumber/HebrewCalendar+JDN.swift | 68 +++++++++---------- Sources/JulianDayNumber/HebrewCalendar.swift | 4 +- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Sources/JulianDayNumber/HebrewCalendar+JDN.swift b/Sources/JulianDayNumber/HebrewCalendar+JDN.swift index 7f17563..eae5fae 100644 --- a/Sources/JulianDayNumber/HebrewCalendar+JDN.swift +++ b/Sources/JulianDayNumber/HebrewCalendar+JDN.swift @@ -8,16 +8,6 @@ import Foundation // Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. -/// The number of years in a cycle of the Hebrew calendar. -/// -/// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. -let hebrewCalendarCycleYears = 689472 - -/// The number of days in a cycle of the Hebrew calendar. -/// -/// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. -let hebrewCalendarCycleDays = 251827457 - extension HebrewCalendar { /// Returns the Julian day number of the first day of Tishrei in the specified year. /// @@ -69,13 +59,23 @@ extension HebrewCalendar: JulianDayNumberConverting { /// A date in the Hebrew calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) + /// The number of years in a cycle of the Hebrew calendar. + /// + /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. + static let calendarCycleYears = 689472 + + /// The number of days in a cycle of the Hebrew calendar. + /// + /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. + static let calendarCycleDays = 251827457 + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 if Y < 1 { - ΔcalendarCycles = (1 - Y) / hebrewCalendarCycleYears + 1 - Y += ΔcalendarCycles * hebrewCalendarCycleYears + ΔcalendarCycles = (1 - Y) / calendarCycleYears + 1 + Y += ΔcalendarCycles * calendarCycleYears } let a = firstDayOfTishrei(year: Y) @@ -84,7 +84,7 @@ extension HebrewCalendar: JulianDayNumberConverting { var J = a + A[K - 1][date.month - 1] + date.day - 1 if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * hebrewCalendarCycleDays + J -= ΔcalendarCycles * calendarCycleDays } return J @@ -95,8 +95,8 @@ extension HebrewCalendar: JulianDayNumberConverting { var ΔcalendarCycles = 0 if J < epochJulianDayNumber { - ΔcalendarCycles = (epochJulianDayNumber - J) / hebrewCalendarCycleDays + 1 - J += ΔcalendarCycles * hebrewCalendarCycleDays + ΔcalendarCycles = (epochJulianDayNumber - J) / calendarCycleDays + 1 + J += ΔcalendarCycles * calendarCycleDays } var Y = yearContaining(julianDayNumber: J) @@ -110,27 +110,27 @@ extension HebrewCalendar: JulianDayNumberConverting { let D = c - AK[M - 1] if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * hebrewCalendarCycleYears + Y -= ΔcalendarCycles * calendarCycleYears } return (Y, M, D) } -} -/// The number of days preceding the first of the month in a year with characterization K. -/// -/// The array is indexed first by `K - 1` and the resultant array by `M - 1`. -private let A = [ - // A deficient common year. - [0, 30, 59, 88, 117, 147, 176, 206, 235, 265, 294, 324], - // A regular common year. - [0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325], - // An abundant common year. - [0, 30, 60, 90, 119, 149, 178, 208, 237, 267, 296, 326], - // A deficient leap year. - [0, 30, 59, 88, 117, 147, 177, 206, 236, 265, 295, 324, 354], - // A regular leap year. - [0, 30, 59, 89, 118, 148, 178, 207, 237, 266, 296, 325, 355], - // An abundant leap year. - [0, 30, 60, 90, 119, 149, 179, 208, 238, 267, 297, 326, 356], -] + /// The number of days preceding the first of the month in a year with characterization K. + /// + /// The array is indexed first by `K - 1` and the resultant array by `M - 1`. + static let A = [ + // A deficient common year. + [0, 30, 59, 88, 117, 147, 176, 206, 235, 265, 294, 324], + // A regular common year. + [0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325], + // An abundant common year. + [0, 30, 60, 90, 119, 149, 178, 208, 237, 267, 296, 326], + // A deficient leap year. + [0, 30, 59, 88, 117, 147, 177, 206, 236, 265, 295, 324, 354], + // A regular leap year. + [0, 30, 59, 89, 118, 148, 178, 207, 237, 266, 296, 325, 355], + // An abundant leap year. + [0, 30, 60, 90, 119, 149, 179, 208, 238, 267, 297, 326, 356], + ] +} diff --git a/Sources/JulianDayNumber/HebrewCalendar.swift b/Sources/JulianDayNumber/HebrewCalendar.swift index 9b1287c..ec93be4 100644 --- a/Sources/JulianDayNumber/HebrewCalendar.swift +++ b/Sources/JulianDayNumber/HebrewCalendar.swift @@ -193,8 +193,8 @@ public struct HebrewCalendar { var ΔcalendarCycles = 0 if Y < 1 { - ΔcalendarCycles = (1 - Y) / hebrewCalendarCycleYears + 1 - Y += ΔcalendarCycles * hebrewCalendarCycleYears + ΔcalendarCycles = (1 - Y) / calendarCycleYears + 1 + Y += ΔcalendarCycles * calendarCycleYears } let a = firstDayOfTishrei(year: Y) From 84c54b7baa03875f74d4bcb4d2390a7ca4259ca1 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 20:31:14 -0600 Subject: [PATCH 04/45] Fix punctuation --- Sources/JulianDayNumber/ArmenianCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/BahaiCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/CopticCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/EgyptianCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/EthiopianCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/GregorianCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/IslamicCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/JulianCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift | 2 +- Sources/JulianDayNumber/SakaCalendar+JDN.swift | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift index d081dcb..cb0a5a2 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift @@ -20,7 +20,7 @@ extension ArmenianCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Armenian calendar consists of 1 year of 365 days. static let calendarCycleDays = 365 - /// The date for Julian day number zero in the proleptic Armenian calendar + /// The date for Julian day number zero in the proleptic Armenian calendar. static let julianDayNumberZero = (year: -5268, month: 11, day: 18) // Constants for Armenian calendar conversions diff --git a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift index 12dd8dc..6a1fca5 100644 --- a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift +++ b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift @@ -20,7 +20,7 @@ extension BahaiCalendar: GregorianIntercalatingJulianDayNumberConverting { /// A cycle in the Baháʼí calendar consists of 303 years of 365 days and 97 leap year of 366 days. static let calendarCycleDays = 146097 - /// The date for Julian day number zero in the Baháʼí Gregorian calendar + /// The date for Julian day number zero in the Baháʼí Gregorian calendar. static let julianDayNumberZero = (year: -6556, month: 14, day: 2) // Constants for Baháʼí calendar conversions diff --git a/Sources/JulianDayNumber/CopticCalendar+JDN.swift b/Sources/JulianDayNumber/CopticCalendar+JDN.swift index db43e9a..2ed3bd0 100644 --- a/Sources/JulianDayNumber/CopticCalendar+JDN.swift +++ b/Sources/JulianDayNumber/CopticCalendar+JDN.swift @@ -20,7 +20,7 @@ extension CopticCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Coptic calendar consists of 3 years of 365 days and 1 leap year of 366 days. static let calendarCycleDays = 1461 - /// The date for Julian day number zero in the Coptic Julian calendar + /// The date for Julian day number zero in the proleptic Coptic calendar. static let julianDayNumberZero = (year: -4996, month: 5, day: 5) // Constants for Coptic calendar conversions diff --git a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift index 706fd9c..168f73a 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift @@ -20,7 +20,7 @@ extension EgyptianCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Egyptian calendar consists of 1 year of 365 days. static let calendarCycleDays = 365 - /// The date for Julian day number zero in the proleptic Egyptian calendar + /// The date for Julian day number zero in the proleptic Egyptian calendar. static let julianDayNumberZero = (year: -3968, month: 2, day: 2) // Constants for Egyptian calendar conversions diff --git a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift index 6ef43c4..5a9bd5b 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift @@ -20,7 +20,7 @@ extension EthiopianCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Ethiopian calendar consists of 3 years of 365 days and 1 leap year of 366 days. static let calendarCycleDays = 1461 - /// The date for Julian day number zero in the proleptic Ethiopian calendar + /// The date for Julian day number zero in the proleptic Ethiopian calendar. static let julianDayNumberZero = (year: -4720, month: 5, day: 5) // Constants for Ethiopian calendar conversions diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift index 7e57bad..c5fccca 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift @@ -20,7 +20,7 @@ extension FrenchRepublicanCalendar: GregorianIntercalatingJulianDayNumberConvert /// A cycle in the modified French Republican calendar consists of 303 years of 365 days and 97 leap year of 366 days. static let calendarCycleDays = 146097 - /// The date for Julian day number zero in the proleptic French Republican calendar + /// The date for Julian day number zero in the proleptic French Republican calendar. static let julianDayNumberZero = (year: -6504, month: 3, day: 3) // Constants for French Republican calendar conversions diff --git a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift index 5489685..61b4abb 100644 --- a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift @@ -20,7 +20,7 @@ extension GregorianCalendar: GregorianIntercalatingJulianDayNumberConverting { /// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. static let calendarCycleDays = 146097 - /// The date for Julian day number zero in the proleptic Gregorian calendar + /// The date for Julian day number zero in the proleptic Gregorian calendar. static let julianDayNumberZero = (year: -4713, month: 11, day: 24) // Constants for Gregorian calendar conversions diff --git a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift index 8892d4a..8a59056 100644 --- a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift +++ b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift @@ -20,7 +20,7 @@ extension IslamicCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Islamic calendar consists of 19 years of 354 days and 11 leap years of 355 days. static let calendarCycleDays = 10631 - /// The date for Julian day number zero in the proleptic Julian calendar + /// The date for Julian day number zero in the proleptic Julian calendar. static let julianDayNumberZero = (year: -5498, month: 8, day: 16) // Constants for Islamic calendar conversions diff --git a/Sources/JulianDayNumber/JulianCalendar+JDN.swift b/Sources/JulianDayNumber/JulianCalendar+JDN.swift index 56fa7c5..6a94a80 100644 --- a/Sources/JulianDayNumber/JulianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/JulianCalendar+JDN.swift @@ -20,7 +20,7 @@ extension JulianCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Julian calendar consists of 3 years of 365 days and 1 leap year of 366 days. static let calendarCycleDays = 1461 - /// The date for Julian day number zero in the proleptic Julian calendar + /// The date for Julian day number zero in the proleptic Julian calendar. static let julianDayNumberZero = (year: -4712, month: 1, day: 1) // Constants for Julian calendar conversions diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift index 282fc83..c5f6479 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift @@ -20,7 +20,7 @@ extension KhwarizmianCalendar: YearMonthDayJulianDayNumberConverting { /// A cycle in the Khwarizmian calendar consists of 1 year of 365 days. static let calendarCycleDays = 365 - /// The date for Julian day number zero in the proleptic Julian calendar + /// The date for Julian day number zero in the proleptic Julian calendar. static let julianDayNumberZero = (year: -5348, month: 11, day: 18) // Constants for Khwarizmian calendar conversions diff --git a/Sources/JulianDayNumber/SakaCalendar+JDN.swift b/Sources/JulianDayNumber/SakaCalendar+JDN.swift index 98c66d6..80bc58d 100644 --- a/Sources/JulianDayNumber/SakaCalendar+JDN.swift +++ b/Sources/JulianDayNumber/SakaCalendar+JDN.swift @@ -22,7 +22,7 @@ extension SakaCalendar: JulianDayNumberConverting { /// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. static let calendarCycleDays = 146097 - /// The date for Julian day number zero in the proleptic Śaka calendar + /// The date for Julian day number zero in the proleptic Śaka calendar. static let julianDayNumberZero = (year: -4791, month: 9, day: 3) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { From 1d618ac6bf8a75f186034eb625c503be3165c3c1 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 22:40:09 -0600 Subject: [PATCH 05/45] Further refactoring --- .../ArmenianCalendar+JDN.swift | 36 +-- .../JulianDayNumber/BahaiCalendar+JDN.swift | 44 ++-- .../JulianDayNumber/CopticCalendar+JDN.swift | 36 +-- .../EgyptianCalendar+JDN.swift | 36 +-- .../EthiopianCalendar+JDN.swift | 36 +-- .../FrenchRepublicanCalendar+JDN.swift | 42 ++- .../GregorianCalendar+JDN.swift | 42 ++- .../JulianDayNumber/HebrewCalendar+JDN.swift | 12 +- .../JulianDayNumber/IslamicCalendar+JDN.swift | 39 +-- Sources/JulianDayNumber/JDN.swift | 239 +++++++++--------- .../JulianDayNumber/JulianCalendar+JDN.swift | 36 +-- .../KhwarizmianCalendar+JDN.swift | 38 +-- .../JulianDayNumber/SakaCalendar+JDN.swift | 24 +- 13 files changed, 275 insertions(+), 385 deletions(-) diff --git a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift index cb0a5a2..181c937 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift @@ -6,34 +6,24 @@ import Foundation -extension ArmenianCalendar: YearMonthDayJulianDayNumberConverting { +extension ArmenianCalendar: JulianDayNumberConverting { /// A date in the Armenian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Armenian calendar. - /// - /// A cycle in the Armenian calendar consists of 1 year. - static let calendarCycleYears = 1 - - /// The number of days in a cycle of the Armenian calendar. - /// - /// A cycle in the Armenian calendar consists of 1 year of 365 days. - static let calendarCycleDays = 365 + /// The intercalating cycle of the Armenian calendar is 1 year of 365 days. + static let intercalatingCycle = (years: 1, days: 365) /// The date for Julian day number zero in the proleptic Armenian calendar. static let julianDayNumberZero = (year: -5268, month: 11, day: 18) - // Constants for Armenian calendar conversions - static let y = 5268 - static let j = 317 - static let m = 0 - static let n = 13 - static let r = 1 - static let p = 365 - static let q = 0 - static let v = 0 - static let u = 1 - static let s = 30 - static let t = 0 - static let w = 0 + /// Algorithm parameters for Armenian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift index 6a1fca5..31ae338 100644 --- a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift +++ b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift @@ -6,37 +6,27 @@ import Foundation -extension BahaiCalendar: GregorianIntercalatingJulianDayNumberConverting { +extension BahaiCalendar: JulianDayNumberConverting { /// A date in the Baháʼí calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Baháʼí calendar. - /// - /// A cycle in the Baháʼí calendar consists of 303 common years and 97 leap years. - static let calendarCycleYears = 400 + /// The intercalating cycle of the Baháʼí calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) - /// The number of days in a cycle of the Baháʼí calendar. - /// - /// A cycle in the Baháʼí calendar consists of 303 years of 365 days and 97 leap year of 366 days. - static let calendarCycleDays = 146097 - - /// The date for Julian day number zero in the Baháʼí Gregorian calendar. + /// The date for Julian day number zero in the proleptic Baháʼí calendar. static let julianDayNumberZero = (year: -6556, month: 14, day: 2) - // Constants for Baháʼí calendar conversions - static let y = 6560 - static let j = 1412 - static let m = 19 - static let n = 20 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 1 - static let s = 19 - static let t = 0 - static let w = 0 - static let A = 184 - static let B = 274273 - static let C = -50 + /// Algorithm parameters for Baháʼí calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0) + + /// Gregorian intercalating parameters for Baháʼí calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274273, C: -50) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/CopticCalendar+JDN.swift b/Sources/JulianDayNumber/CopticCalendar+JDN.swift index 2ed3bd0..83fb5e8 100644 --- a/Sources/JulianDayNumber/CopticCalendar+JDN.swift +++ b/Sources/JulianDayNumber/CopticCalendar+JDN.swift @@ -6,34 +6,24 @@ import Foundation -extension CopticCalendar: YearMonthDayJulianDayNumberConverting { +extension CopticCalendar: JulianDayNumberConverting { /// A date in the Coptic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Coptic calendar. - /// - /// A cycle in the Coptic calendar consists of 3 common years and 1 leap year. - static let calendarCycleYears = 4 - - /// The number of days in a cycle of the Coptic calendar. - /// - /// A cycle in the Coptic calendar consists of 3 years of 365 days and 1 leap year of 366 days. - static let calendarCycleDays = 1461 + /// The intercalating cycle of the Coptic calendar is 3 common years of 365 days and 1 leap year of 366 days. + static let intercalatingCycle = (years: 4, days: 1461) /// The date for Julian day number zero in the proleptic Coptic calendar. static let julianDayNumberZero = (year: -4996, month: 5, day: 5) - // Constants for Coptic calendar conversions - static let y = 4996 - static let j = 124 - static let m = 0 - static let n = 13 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 1 - static let s = 30 - static let t = 0 - static let w = 0 + /// Algorithm parameters for Coptic calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift index 168f73a..aed14e4 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift @@ -6,34 +6,24 @@ import Foundation -extension EgyptianCalendar: YearMonthDayJulianDayNumberConverting { +extension EgyptianCalendar: JulianDayNumberConverting { /// A date in the Egyptian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Egyptian calendar. - /// - /// A cycle in the Egyptian calendar consists of 1 year. - static let calendarCycleYears = 1 - - /// The number of days in a cycle of the Egyptian calendar. - /// - /// A cycle in the Egyptian calendar consists of 1 year of 365 days. - static let calendarCycleDays = 365 + /// The intercalating cycle of the Egyptian calendar is 1 year of 365 days. + static let intercalatingCycle = (years: 1, days: 365) /// The date for Julian day number zero in the proleptic Egyptian calendar. static let julianDayNumberZero = (year: -3968, month: 2, day: 2) - // Constants for Egyptian calendar conversions - static let y = 3968 - static let j = 47 - static let m = 0 - static let n = 13 - static let r = 1 - static let p = 365 - static let q = 0 - static let v = 0 - static let u = 1 - static let s = 30 - static let t = 0 - static let w = 0 + /// Algorithm parameters for Egyptian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift index 5a9bd5b..eff1ea6 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift @@ -6,34 +6,24 @@ import Foundation -extension EthiopianCalendar: YearMonthDayJulianDayNumberConverting { +extension EthiopianCalendar: JulianDayNumberConverting { /// A date in the Ethiopian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Ethiopian calendar. - /// - /// A cycle in the Ethiopian calendar consists of 3 common years and 1 leap year. - static let calendarCycleYears = 4 - - /// The number of days in a cycle of the Ethiopian calendar. - /// - /// A cycle in the Ethiopian calendar consists of 3 years of 365 days and 1 leap year of 366 days. - static let calendarCycleDays = 1461 + /// The intercalating cycle of the Ethiopian calendar is 3 common years of 365 days and 1 leap year of 366 days. + static let intercalatingCycle = (years: 4, days: 1461) /// The date for Julian day number zero in the proleptic Ethiopian calendar. static let julianDayNumberZero = (year: -4720, month: 5, day: 5) - // Constants for Ethiopian calendar conversions - static let y = 4720 - static let j = 124 - static let m = 0 - static let n = 13 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 1 - static let s = 30 - static let t = 0 - static let w = 0 + /// Algorithm parameters for Ethiopian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift index c5fccca..832f7b1 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift @@ -6,37 +6,27 @@ import Foundation -extension FrenchRepublicanCalendar: GregorianIntercalatingJulianDayNumberConverting { +extension FrenchRepublicanCalendar: JulianDayNumberConverting { /// A date in the French Republican calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the French Republican calendar. - /// - /// A cycle in the modified French Republican calendar consists of 303 common years and 97 leap years. - static let calendarCycleYears = 400 - - /// The number of days in a cycle of the French Republican calendar. - /// - /// A cycle in the modified French Republican calendar consists of 303 years of 365 days and 97 leap year of 366 days. - static let calendarCycleDays = 146097 + /// The intercalating cycle of the French Republican calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) /// The date for Julian day number zero in the proleptic French Republican calendar. static let julianDayNumberZero = (year: -6504, month: 3, day: 3) - // Constants for French Republican calendar conversions - static let y = 6504 - static let j = 111 - static let m = 0 - static let n = 13 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 1 - static let s = 30 - static let t = 0 - static let w = 0 - static let A = 396 - static let B = 578797 - static let C = -51 + /// Algorithm parameters for French Republican calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + + /// Gregorian intercalating parameters for French Republican calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 396, B: 578797, C: -51) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift index 61b4abb..32124a8 100644 --- a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift @@ -6,37 +6,27 @@ import Foundation -extension GregorianCalendar: GregorianIntercalatingJulianDayNumberConverting { +extension GregorianCalendar: JulianDayNumberConverting { /// A date in the Gregorian calendar consists of a year, month, and day. public typealias DateType = JulianCalendar.DateType - /// The number of years in a cycle of the Gregorian calendar. - /// - /// A cycle in the Gregorian calendar consists of 303 common years and 97 leap years. - static let calendarCycleYears = 400 - - /// The number of days in a cycle of the Gregorian calendar. - /// - /// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. - static let calendarCycleDays = 146097 + /// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) /// The date for Julian day number zero in the proleptic Gregorian calendar. static let julianDayNumberZero = (year: -4713, month: 11, day: 24) - // Constants for Gregorian calendar conversions - static let y = 4716 - static let j = 1401 - static let m = 2 - static let n = 12 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 5 - static let s = 153 - static let t = 2 - static let w = 2 - static let A = 184 - static let B = 274277 - static let C = -38 + /// Algorithm parameters for Gregorian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) + + /// Gregorian intercalating parameters for Gregorian calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274277, C: -38) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/HebrewCalendar+JDN.swift b/Sources/JulianDayNumber/HebrewCalendar+JDN.swift index eae5fae..24774a2 100644 --- a/Sources/JulianDayNumber/HebrewCalendar+JDN.swift +++ b/Sources/JulianDayNumber/HebrewCalendar+JDN.swift @@ -11,14 +11,14 @@ import Foundation extension HebrewCalendar { /// Returns the Julian day number of the first day of Tishrei in the specified year. /// - /// - note: No validation check is performed on the year value. + /// - attention: No validation check is performed on the year value. /// /// - parameter Y: A year A.M. /// /// - returns: The Julian day number of the first day of Tishrei in the specified year. static func firstDayOfTishrei(year Y: Int) -> JulianDayNumber { -// precondition(Y > 0, "First day of Tishrei calculations only valid for year numbers > 0") -// precondition(Y < 974245219737, "Year values above 974245219736 cause numerical overflow using 64-bit integers") + precondition(Y > 0, "First day of Tishrei calculations only valid for year numbers > 0") + precondition(Y < 974245219737, "Year values above 974245219736 cause numerical overflow using 64-bit integers") // It is possible to adjust the year by a multiple of the cycle to have this function // calculate correct values for the first day of Tishrei in proleptic years. However, @@ -42,8 +42,8 @@ extension HebrewCalendar { /// /// - returns: The year containing the specified Julian day number. static func yearContaining(julianDayNumber J: JulianDayNumber) -> Int { -// precondition(J >= epochJulianDayNumber, "Julian day number must be >= epoch") -// precondition(J < 355839970905665, "Julian day numbers above 355839970905664 cause numerical overflow using 64-bit integers") + precondition(J >= epochJulianDayNumber, "Julian day number must be >= epoch") + precondition(J < 355839970905665, "Julian day numbers above 355839970905664 cause numerical overflow using 64-bit integers") let M = (25920 * (J - 347996)) / 765433 + 1 var Y = 19 * (M / 235) + (19 * (M % 235) - 2) / 235 + 1 @@ -104,7 +104,7 @@ extension HebrewCalendar: JulianDayNumberConverting { let b = firstDayOfTishrei(year: Y + 1) let K = b - a - 352 - 27 * (((7 * Y + 13) % 19) / 12) let c = J - a + 1 -// precondition(c >= 0) + precondition(c >= 0) let AK = A[K - 1] let M = AK.lastIndex(where: {$0 < c})! + 1 let D = c - AK[M - 1] diff --git a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift index 8a59056..a48e213 100644 --- a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift +++ b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift @@ -6,35 +6,24 @@ import Foundation -extension IslamicCalendar: YearMonthDayJulianDayNumberConverting { +extension IslamicCalendar: JulianDayNumberConverting { /// A date in the Islamic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Islamic calendar. - /// - /// A cycle in the Islamic calendar consists of 19 common years and 11 leap years. - static let calendarCycleYears = 30 + /// The intercalating cycle of the Islamic calendar is 19 common years of 354 days and 11 leap years of 355 days. + static let intercalatingCycle = (years: 30, days: 10631) - /// The number of days in a cycle of the Islamic calendar. - /// - /// A cycle in the Islamic calendar consists of 19 years of 354 days and 11 leap years of 355 days. - static let calendarCycleDays = 10631 - - /// The date for Julian day number zero in the proleptic Julian calendar. + /// The date for Julian day number zero in the proleptic Islamic calendar. static let julianDayNumberZero = (year: -5498, month: 8, day: 16) - // Constants for Islamic calendar conversions - static let y = 5519 - static let j = 7664 - // Islamic A is identical except j = 7665 - static let m = 0 - static let n = 12 - static let r = 30 - static let p = 10631 - static let q = 14 - static let v = 15 - static let u = 100 - static let s = 2951 - static let t = 51 - static let w = 10 + /// Algorithm parameters for Islamic calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/JDN.swift b/Sources/JulianDayNumber/JDN.swift index aef6b98..0e8cdc5 100644 --- a/Sources/JulianDayNumber/JDN.swift +++ b/Sources/JulianDayNumber/JDN.swift @@ -55,154 +55,153 @@ extension JulianDayNumberConverting where DateType == (year: Int, month: Int, da // MARK: - Conversion Algorithms -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -protocol YearMonthDayJulianDayNumberConverting: JulianDayNumberConverting where DateType == (year: Int, month: Int, day: Int) { - static var calendarCycleDays: Int { get } - static var calendarCycleYears: Int { get } - static var julianDayNumberZero: DateType { get } - - static var y: Int { get } - static var j: Int { get } - static var m: Int { get } - static var n: Int { get } - static var r: Int { get } - static var p: Int { get } - static var q: Int { get } - static var v: Int { get } - static var u: Int { get } - static var s: Int { get } - static var t: Int { get } - static var w: Int { get } +// Algorithms from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. + +/// Algorithm parameters for converting a Julian day number to a year, month, and day. +struct JDNConversionParameters { + let y: Int + let j: Int + let m: Int + let n: Int + let r: Int + let p: Int + let q: Int + let v: Int + let u: Int + let s: Int + let t: Int + let w: Int } -extension YearMonthDayJulianDayNumberConverting { - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 +/// Algorithm parameters specific to calenders using Gregorian-type intercalating. +struct JDNGregorianIntercalatingParameters { + let A: Int + let B: Int + let C: Int +} + +/// A calendar's intercalating cycle. +typealias IntercalatingCycle = (years: Int, days: Int) - if date < julianDayNumberZero { - ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / calendarCycleYears + 1 - Y += ΔcalendarCycles * calendarCycleYears - } +/// A date consisting of a year, month, and day. +typealias YearMonthDay = (year: Int, month: Int, day: Int) - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u +/// Converts a date to a Julian day number using the specified conversion parameters and returns the result. +/// +/// - important: No validation checks are performed on the date values. +/// +/// - parameter date: A date to convert. +/// - parameter parameters: Parameters for the conversion algorithm. +/// - parameter jdnZero: The date for which the Julian day number is zero. +/// - parameter intercalatingCycle: The calendar's intercalating cycle. +/// +/// - returns: The Julian day number corresponding to the specified date. +func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, jdnZero: YearMonthDay, intercalatingCycle: IntercalatingCycle) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if date < jdnZero { + ΔcalendarCycles = (jdnZero.year - Y - 1) / intercalatingCycle.years + 1 + Y += ΔcalendarCycles * intercalatingCycle.years + } - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * calendarCycleDays - } + let h = date.month - parameters.m + let g = Y + parameters.y - (parameters.n - h) / parameters.n + let f = (h - 1 + parameters.n) % parameters.n + let e = (parameters.p * g + parameters.q) / parameters.r + date.day - 1 - parameters.j + var J = e + (parameters.s * f + parameters.t) / parameters.u - return J + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * intercalatingCycle.days } - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { -// precondition(J < Int.max - 1) + return J +} - var J = J - var ΔcalendarCycles = 0 +/// Converts a Julian day number to a date and returns the result. +/// +/// - parameter J: A Julian day number. +/// - parameter parameters: Parameters for the conversion algorithm. +/// - parameter intercalatingCycle: The calendar's intercalating cycle. +/// +/// - returns: The date corresponding to the specified Julian day number. +func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, intercalatingCycle: IntercalatingCycle) -> YearMonthDay { +// precondition(J < Int.max - 1) - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / calendarCycleDays + 1 - J += ΔcalendarCycles * calendarCycleDays - } + var J = J + var ΔcalendarCycles = 0 - precondition(J <= Int.max - j, "Julian day number too large") + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / intercalatingCycle.days + 1 + J += ΔcalendarCycles * intercalatingCycle.days + } - let f = J + j - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n + precondition(J <= Int.max - parameters.j, "Julian day number too large") - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * calendarCycleYears - } + let f = J + parameters.j + let e = parameters.r * f + parameters.v + let g = (e % parameters.p) / parameters.r + let h = parameters.u * g + parameters.w + let D = (h % parameters.s) / parameters.u + 1 + let M = ((h / parameters.s + parameters.m) % parameters.n) + 1 + var Y = e / parameters.p - parameters.y + (parameters.n + parameters.m - M) / parameters.n - return (Y, M, D) + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * intercalatingCycle.years } -} -// MARK: Gregorian-type Intercalation - -protocol GregorianIntercalatingJulianDayNumberConverting: JulianDayNumberConverting where DateType == (year: Int, month: Int, day: Int) { - static var calendarCycleDays: Int { get } - static var calendarCycleYears: Int { get } - static var julianDayNumberZero: DateType { get } - - static var y: Int { get } - static var j: Int { get } - static var m: Int { get } - static var n: Int { get } - static var r: Int { get } - static var p: Int { get } - static var q: Int { get } - static var v: Int { get } - static var u: Int { get } - static var s: Int { get } - static var t: Int { get } - static var w: Int { get } - static var A: Int { get } - static var B: Int { get } - static var C: Int { get } + return (Y, M, D) } -extension GregorianIntercalatingJulianDayNumberConverting { - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - if date < julianDayNumberZero { - ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / calendarCycleYears + 1 - Y += ΔcalendarCycles * calendarCycleYears - } +func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters, jdnZero: YearMonthDay, intercalatingCycle: IntercalatingCycle) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - var J = e + (s * f + t) / u - J = J - (3 * ((g + A) / 100)) / 4 - C + if date < jdnZero { + ΔcalendarCycles = (jdnZero.year - Y - 1) / intercalatingCycle.years + 1 + Y += ΔcalendarCycles * intercalatingCycle.years + } - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * calendarCycleDays - } + let h = date.month - parameters.m + let g = Y + parameters.y - (parameters.n - h) / parameters.n + let f = (h - 1 + parameters.n) % parameters.n + let e = (parameters.p * g + parameters.q) / parameters.r + date.day - 1 - parameters.j + var J = e + (parameters.s * f + parameters.t) / parameters.u + J = J - (3 * ((g + gregorianIntercalatingParameters.A) / 100)) / 4 - gregorianIntercalatingParameters.C - return J + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * intercalatingCycle.days } - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 + return J +} - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / calendarCycleDays + 1 - J += ΔcalendarCycles * calendarCycleDays - } +func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters, intercalatingCycle: IntercalatingCycle) -> YearMonthDay { + var J = J + var ΔcalendarCycles = 0 - precondition(J <= Int.max - j, "Julian day number too large") + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / intercalatingCycle.days + 1 + J += ΔcalendarCycles * intercalatingCycle.days + } - var f = J + j - f = f + (((4 * J + B) / 146097) * 3) / 4 + C - let e = r * f + v - let g = (e % p) / r - let h = u * g + w - let D = (h % s) / u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n + precondition(J <= Int.max - parameters.j, "Julian day number too large") - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * calendarCycleYears - } + var f = J + parameters.j + f = f + (((4 * J + gregorianIntercalatingParameters.B) / 146097) * 3) / 4 + gregorianIntercalatingParameters.C + let e = parameters.r * f + parameters.v + let g = (e % parameters.p) / parameters.r + let h = parameters.u * g + parameters.w + let D = (h % parameters.s) / parameters.u + 1 + let M = ((h / parameters.s + parameters.m) % parameters.n) + 1 + var Y = e / parameters.p - parameters.y + (parameters.n + parameters.m - M) / parameters.n - return (Y, M, D) + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * intercalatingCycle.years } -} + return (Y, M, D) +} diff --git a/Sources/JulianDayNumber/JulianCalendar+JDN.swift b/Sources/JulianDayNumber/JulianCalendar+JDN.swift index 6a94a80..eb7da56 100644 --- a/Sources/JulianDayNumber/JulianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/JulianCalendar+JDN.swift @@ -6,34 +6,24 @@ import Foundation -extension JulianCalendar: YearMonthDayJulianDayNumberConverting { +extension JulianCalendar: JulianDayNumberConverting { /// A date in the Julian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Julian calendar. - /// - /// A cycle in the Julian calendar consists of 3 common years and 1 leap year. - static let calendarCycleYears = 4 - - /// The number of days in a cycle of the Julian calendar. - /// - /// A cycle in the Julian calendar consists of 3 years of 365 days and 1 leap year of 366 days. - static let calendarCycleDays = 1461 + /// The intercalating cycle of the Julian calendar is 3 common years of 365 days and 1 leap year of 366 days. + static let intercalatingCycle = (years: 4, days: 1461) /// The date for Julian day number zero in the proleptic Julian calendar. static let julianDayNumberZero = (year: -4712, month: 1, day: 1) - // Constants for Julian calendar conversions - static let y = 4716 - static let j = 1401 - static let m = 2 - static let n = 12 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 5 - static let s = 153 - static let t = 2 - static let w = 2 + /// Algorithm parameters for Julian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift index c5f6479..af23767 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift @@ -6,34 +6,24 @@ import Foundation -extension KhwarizmianCalendar: YearMonthDayJulianDayNumberConverting { +extension KhwarizmianCalendar: JulianDayNumberConverting { /// A date in the Khwarizmian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Khwarizmian calendar. - /// - /// A cycle in the Khwarizmian calendar consists of 1 year. - static let calendarCycleYears = 1 + /// The intercalating cycle of the Khwarizmian calendar is 1 year of 365 days. + static let intercalatingCycle = (years: 1, days: 365) - /// The number of days in a cycle of the Khwarizmian calendar. - /// - /// A cycle in the Khwarizmian calendar consists of 1 year of 365 days. - static let calendarCycleDays = 365 - - /// The date for Julian day number zero in the proleptic Julian calendar. + /// The date for Julian day number zero in the proleptic Khwarizmian calendar. static let julianDayNumberZero = (year: -5348, month: 11, day: 18) - // Constants for Khwarizmian calendar conversions - static let y = 5348 - static let j = 317 - static let m = 0 - static let n = 13 - static let r = 1 - static let p = 365 - static let q = 0 - static let v = 0 - static let u = 1 - static let s = 30 - static let t = 0 - static let w = 0 + /// Algorithm parameters for Khwarizmian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } } diff --git a/Sources/JulianDayNumber/SakaCalendar+JDN.swift b/Sources/JulianDayNumber/SakaCalendar+JDN.swift index 80bc58d..51a24c4 100644 --- a/Sources/JulianDayNumber/SakaCalendar+JDN.swift +++ b/Sources/JulianDayNumber/SakaCalendar+JDN.swift @@ -12,15 +12,8 @@ extension SakaCalendar: JulianDayNumberConverting { /// A date in the Śaka calendar consists of a year, month, and day. public typealias DateType = (year: Int, month: Int, day: Int) - /// The number of years in a cycle of the Śaka calendar. - /// - /// A cycle in the Śaka calendar consists of 303 common years and 97 leap years. - static let calendarCycleYears = 400 - - /// The number of days in a cycle of the Śaka calendar. - /// - /// A cycle in the Gregorian calendar consists of 303 years of 365 days and 97 leap year of 366 days. - static let calendarCycleDays = 146097 + /// The intercalating cycle of the Śaka calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) /// The date for Julian day number zero in the proleptic Śaka calendar. static let julianDayNumberZero = (year: -4791, month: 9, day: 3) @@ -29,10 +22,9 @@ extension SakaCalendar: JulianDayNumberConverting { var Y = date.year var ΔcalendarCycles = 0 - // JDN 0 is -4791-09-03 in the proleptic Śaka calendar. if date < julianDayNumberZero { - ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / calendarCycleYears + 1 - Y += ΔcalendarCycles * calendarCycleYears + ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / intercalatingCycle.years + 1 + Y += ΔcalendarCycles * intercalatingCycle.years } let h = date.month - m @@ -44,7 +36,7 @@ extension SakaCalendar: JulianDayNumberConverting { J = J - (3 * ((g + A) / 100)) / 4 - C if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * calendarCycleDays + J -= ΔcalendarCycles * intercalatingCycle.days } return J @@ -56,8 +48,8 @@ extension SakaCalendar: JulianDayNumberConverting { // Richards' algorithm is only valid for positive JDNs. if J < 0 { - ΔcalendarCycles = -J / calendarCycleDays + 1 - J += ΔcalendarCycles * calendarCycleDays + ΔcalendarCycles = -J / intercalatingCycle.days + 1 + J += ΔcalendarCycles * intercalatingCycle.days } var f = J + j @@ -75,7 +67,7 @@ extension SakaCalendar: JulianDayNumberConverting { var Y = e / p - y + (n + m - M) / n if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * calendarCycleYears + Y -= ΔcalendarCycles * intercalatingCycle.years } return (Y, M, D) From 2eb6fce96bb03a4bac46ff3d9b45f7af64cab94c Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 22:46:09 -0600 Subject: [PATCH 06/45] Consolidate source files --- .../ArmenianCalendar+JDN.swift | 29 ---- .../JulianDayNumber/ArmenianCalendar.swift | 22 +++ .../AstronomicalCalendar+JDN.swift | 36 ----- .../AstronomicalCalendar.swift | 29 ++++ .../JulianDayNumber/BahaiCalendar+JDN.swift | 32 ----- Sources/JulianDayNumber/BahaiCalendar.swift | 25 ++++ .../JulianDayNumber/CopticCalendar+JDN.swift | 29 ---- Sources/JulianDayNumber/CopticCalendar.swift | 22 +++ .../EgyptianCalendar+JDN.swift | 29 ---- .../JulianDayNumber/EgyptianCalendar.swift | 22 +++ .../EthiopianCalendar+JDN.swift | 29 ---- .../JulianDayNumber/EthiopianCalendar.swift | 22 +++ .../FrenchRepublicanCalendar+JDN.swift | 32 ----- .../FrenchRepublicanCalendar.swift | 25 ++++ .../GregorianCalendar+JDN.swift | 32 ----- .../JulianDayNumber/GregorianCalendar.swift | 25 ++++ .../JulianDayNumber/HebrewCalendar+JDN.swift | 136 ------------------ Sources/JulianDayNumber/HebrewCalendar.swift | 129 +++++++++++++++++ .../JulianDayNumber/IslamicCalendar+JDN.swift | 29 ---- Sources/JulianDayNumber/IslamicCalendar.swift | 22 +++ .../JulianDayNumber/JulianCalendar+JDN.swift | 29 ---- Sources/JulianDayNumber/JulianCalendar.swift | 22 +++ .../KhwarizmianCalendar+JDN.swift | 29 ---- .../JulianDayNumber/KhwarizmianCalendar.swift | 22 +++ .../JulianDayNumber/SakaCalendar+JDN.swift | 92 ------------ Sources/JulianDayNumber/SakaCalendar.swift | 85 +++++++++++ 26 files changed, 472 insertions(+), 563 deletions(-) delete mode 100644 Sources/JulianDayNumber/ArmenianCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/AstronomicalCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/BahaiCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/CopticCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/EgyptianCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/EthiopianCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/GregorianCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/HebrewCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/IslamicCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/JulianCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift delete mode 100644 Sources/JulianDayNumber/SakaCalendar+JDN.swift diff --git a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift b/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift deleted file mode 100644 index 181c937..0000000 --- a/Sources/JulianDayNumber/ArmenianCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension ArmenianCalendar: JulianDayNumberConverting { - /// A date in the Armenian calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Armenian calendar is 1 year of 365 days. - static let intercalatingCycle = (years: 1, days: 365) - - /// The date for Julian day number zero in the proleptic Armenian calendar. - static let julianDayNumberZero = (year: -5268, month: 11, day: 18) - - /// Algorithm parameters for Armenian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/ArmenianCalendar.swift b/Sources/JulianDayNumber/ArmenianCalendar.swift index f16c5d8..acb982c 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar.swift @@ -78,3 +78,25 @@ public struct ArmenianCalendar { return monthLengths[M - 1] } } + +extension ArmenianCalendar: JulianDayNumberConverting { + /// A date in the Armenian calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Armenian calendar is 1 year of 365 days. + static let intercalatingCycle = (years: 1, days: 365) + + /// The date for Julian day number zero in the proleptic Armenian calendar. + static let julianDayNumberZero = (year: -5268, month: 11, day: 18) + + /// Algorithm parameters for Armenian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/AstronomicalCalendar+JDN.swift b/Sources/JulianDayNumber/AstronomicalCalendar+JDN.swift deleted file mode 100644 index 0b37bdd..0000000 --- a/Sources/JulianDayNumber/AstronomicalCalendar+JDN.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension AstronomicalCalendar: JulianDayNumberConverting { - /// A date in the astronomical calendar consists of a year, month, and day in either the Julian or Gregorian calendar. - public typealias DateType = JulianCalendar.DateType - - /// Converts a date in the astromical calendar to a Julian day number. - /// - /// Dates before October 15, 1582 are treated as dates in the Julian calendar while later dates are treated as dates in the Gregorian calendar. - /// - /// - important: No validation checks are performed on the date values. - /// - /// - parameter date: A date to convert. - /// - /// - returns: The Julian day number corresponding to the specified date. - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - date < gregorianCalendarEffectiveDate ? JulianCalendar.julianDayNumberFromDate(date) : GregorianCalendar.julianDayNumberFromDate(date) - } - - /// Converts a Julian day number to a date in the astromical calendar. - /// - /// Julian day numbers less than 2299161 treated as dates in the Julian calendar while equal or larger Julian day numbers are treated as dates in the Gregorian calendar. - /// - /// - parameter J: A Julian day number. - /// - /// - returns: The date corresponding to the specified Julian day number. - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - J < GregorianCalendar.effectiveJulianDayNumber ? JulianCalendar.dateFromJulianDayNumber(J): GregorianCalendar.dateFromJulianDayNumber(J) - } -} diff --git a/Sources/JulianDayNumber/AstronomicalCalendar.swift b/Sources/JulianDayNumber/AstronomicalCalendar.swift index 443182b..eb5f6e0 100644 --- a/Sources/JulianDayNumber/AstronomicalCalendar.swift +++ b/Sources/JulianDayNumber/AstronomicalCalendar.swift @@ -87,3 +87,32 @@ public struct AstronomicalCalendar { Y < gregorianCalendarEffectiveDate.year ? JulianCalendar.easter(year: Y) : GregorianCalendar.easter(year: Y) } } + +extension AstronomicalCalendar: JulianDayNumberConverting { + /// A date in the astronomical calendar consists of a year, month, and day in either the Julian or Gregorian calendar. + public typealias DateType = JulianCalendar.DateType + + /// Converts a date in the astromical calendar to a Julian day number. + /// + /// Dates before October 15, 1582 are treated as dates in the Julian calendar while later dates are treated as dates in the Gregorian calendar. + /// + /// - important: No validation checks are performed on the date values. + /// + /// - parameter date: A date to convert. + /// + /// - returns: The Julian day number corresponding to the specified date. + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + date < gregorianCalendarEffectiveDate ? JulianCalendar.julianDayNumberFromDate(date) : GregorianCalendar.julianDayNumberFromDate(date) + } + + /// Converts a Julian day number to a date in the astromical calendar. + /// + /// Julian day numbers less than 2299161 treated as dates in the Julian calendar while equal or larger Julian day numbers are treated as dates in the Gregorian calendar. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The date corresponding to the specified Julian day number. + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + J < GregorianCalendar.effectiveJulianDayNumber ? JulianCalendar.dateFromJulianDayNumber(J): GregorianCalendar.dateFromJulianDayNumber(J) + } +} diff --git a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift b/Sources/JulianDayNumber/BahaiCalendar+JDN.swift deleted file mode 100644 index 31ae338..0000000 --- a/Sources/JulianDayNumber/BahaiCalendar+JDN.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension BahaiCalendar: JulianDayNumberConverting { - /// A date in the Baháʼí calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Baháʼí calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic Baháʼí calendar. - static let julianDayNumberZero = (year: -6556, month: 14, day: 2) - - /// Algorithm parameters for Baháʼí calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0) - - /// Gregorian intercalating parameters for Baháʼí calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274273, C: -50) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/BahaiCalendar.swift b/Sources/JulianDayNumber/BahaiCalendar.swift index 40886cd..e884a53 100644 --- a/Sources/JulianDayNumber/BahaiCalendar.swift +++ b/Sources/JulianDayNumber/BahaiCalendar.swift @@ -134,3 +134,28 @@ public struct BahaiCalendar { } } } + +extension BahaiCalendar: JulianDayNumberConverting { + /// A date in the Baháʼí calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Baháʼí calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) + + /// The date for Julian day number zero in the proleptic Baháʼí calendar. + static let julianDayNumberZero = (year: -6556, month: 14, day: 2) + + /// Algorithm parameters for Baháʼí calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0) + + /// Gregorian intercalating parameters for Baháʼí calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274273, C: -50) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/CopticCalendar+JDN.swift b/Sources/JulianDayNumber/CopticCalendar+JDN.swift deleted file mode 100644 index 83fb5e8..0000000 --- a/Sources/JulianDayNumber/CopticCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension CopticCalendar: JulianDayNumberConverting { - /// A date in the Coptic calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Coptic calendar is 3 common years of 365 days and 1 leap year of 366 days. - static let intercalatingCycle = (years: 4, days: 1461) - - /// The date for Julian day number zero in the proleptic Coptic calendar. - static let julianDayNumberZero = (year: -4996, month: 5, day: 5) - - /// Algorithm parameters for Coptic calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/CopticCalendar.swift b/Sources/JulianDayNumber/CopticCalendar.swift index 81f7fae..6bc9c65 100644 --- a/Sources/JulianDayNumber/CopticCalendar.swift +++ b/Sources/JulianDayNumber/CopticCalendar.swift @@ -95,3 +95,25 @@ public struct CopticCalendar { } } } + +extension CopticCalendar: JulianDayNumberConverting { + /// A date in the Coptic calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Coptic calendar is 3 common years of 365 days and 1 leap year of 366 days. + static let intercalatingCycle = (years: 4, days: 1461) + + /// The date for Julian day number zero in the proleptic Coptic calendar. + static let julianDayNumberZero = (year: -4996, month: 5, day: 5) + + /// Algorithm parameters for Coptic calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift b/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift deleted file mode 100644 index aed14e4..0000000 --- a/Sources/JulianDayNumber/EgyptianCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension EgyptianCalendar: JulianDayNumberConverting { - /// A date in the Egyptian calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Egyptian calendar is 1 year of 365 days. - static let intercalatingCycle = (years: 1, days: 365) - - /// The date for Julian day number zero in the proleptic Egyptian calendar. - static let julianDayNumberZero = (year: -3968, month: 2, day: 2) - - /// Algorithm parameters for Egyptian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/EgyptianCalendar.swift b/Sources/JulianDayNumber/EgyptianCalendar.swift index 16c3ab6..a46567b 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar.swift @@ -79,3 +79,25 @@ public struct EgyptianCalendar { return monthLengths[M - 1] } } + +extension EgyptianCalendar: JulianDayNumberConverting { + /// A date in the Egyptian calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Egyptian calendar is 1 year of 365 days. + static let intercalatingCycle = (years: 1, days: 365) + + /// The date for Julian day number zero in the proleptic Egyptian calendar. + static let julianDayNumberZero = (year: -3968, month: 2, day: 2) + + /// Algorithm parameters for Egyptian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift b/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift deleted file mode 100644 index eff1ea6..0000000 --- a/Sources/JulianDayNumber/EthiopianCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension EthiopianCalendar: JulianDayNumberConverting { - /// A date in the Ethiopian calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Ethiopian calendar is 3 common years of 365 days and 1 leap year of 366 days. - static let intercalatingCycle = (years: 4, days: 1461) - - /// The date for Julian day number zero in the proleptic Ethiopian calendar. - static let julianDayNumberZero = (year: -4720, month: 5, day: 5) - - /// Algorithm parameters for Ethiopian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/EthiopianCalendar.swift b/Sources/JulianDayNumber/EthiopianCalendar.swift index 406361a..ab265b7 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar.swift @@ -95,3 +95,25 @@ public struct EthiopianCalendar { } } } + +extension EthiopianCalendar: JulianDayNumberConverting { + /// A date in the Ethiopian calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Ethiopian calendar is 3 common years of 365 days and 1 leap year of 366 days. + static let intercalatingCycle = (years: 4, days: 1461) + + /// The date for Julian day number zero in the proleptic Ethiopian calendar. + static let julianDayNumberZero = (year: -4720, month: 5, day: 5) + + /// Algorithm parameters for Ethiopian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift deleted file mode 100644 index 832f7b1..0000000 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar+JDN.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension FrenchRepublicanCalendar: JulianDayNumberConverting { - /// A date in the French Republican calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the French Republican calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic French Republican calendar. - static let julianDayNumberZero = (year: -6504, month: 3, day: 3) - - /// Algorithm parameters for French Republican calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) - - /// Gregorian intercalating parameters for French Republican calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 396, B: 578797, C: -51) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift index c5b32b7..4cade50 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift @@ -132,3 +132,28 @@ public struct FrenchRepublicanCalendar { } } } + +extension FrenchRepublicanCalendar: JulianDayNumberConverting { + /// A date in the French Republican calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the French Republican calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) + + /// The date for Julian day number zero in the proleptic French Republican calendar. + static let julianDayNumberZero = (year: -6504, month: 3, day: 3) + + /// Algorithm parameters for French Republican calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + + /// Gregorian intercalating parameters for French Republican calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 396, B: 578797, C: -51) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift b/Sources/JulianDayNumber/GregorianCalendar+JDN.swift deleted file mode 100644 index 32124a8..0000000 --- a/Sources/JulianDayNumber/GregorianCalendar+JDN.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension GregorianCalendar: JulianDayNumberConverting { - /// A date in the Gregorian calendar consists of a year, month, and day. - public typealias DateType = JulianCalendar.DateType - - /// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic Gregorian calendar. - static let julianDayNumberZero = (year: -4713, month: 11, day: 24) - - /// Algorithm parameters for Gregorian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) - - /// Gregorian intercalating parameters for Gregorian calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274277, C: -38) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/GregorianCalendar.swift b/Sources/JulianDayNumber/GregorianCalendar.swift index 8d5e983..0596c52 100644 --- a/Sources/JulianDayNumber/GregorianCalendar.swift +++ b/Sources/JulianDayNumber/GregorianCalendar.swift @@ -173,3 +173,28 @@ public struct GregorianCalendar { return (M, D) } } + +extension GregorianCalendar: JulianDayNumberConverting { + /// A date in the Gregorian calendar consists of a year, month, and day. + public typealias DateType = JulianCalendar.DateType + + /// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) + + /// The date for Julian day number zero in the proleptic Gregorian calendar. + static let julianDayNumberZero = (year: -4713, month: 11, day: 24) + + /// Algorithm parameters for Gregorian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) + + /// Gregorian intercalating parameters for Gregorian calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274277, C: -38) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/HebrewCalendar+JDN.swift b/Sources/JulianDayNumber/HebrewCalendar+JDN.swift deleted file mode 100644 index 24774a2..0000000 --- a/Sources/JulianDayNumber/HebrewCalendar+JDN.swift +++ /dev/null @@ -1,136 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -extension HebrewCalendar { - /// Returns the Julian day number of the first day of Tishrei in the specified year. - /// - /// - attention: No validation check is performed on the year value. - /// - /// - parameter Y: A year A.M. - /// - /// - returns: The Julian day number of the first day of Tishrei in the specified year. - static func firstDayOfTishrei(year Y: Int) -> JulianDayNumber { - precondition(Y > 0, "First day of Tishrei calculations only valid for year numbers > 0") - precondition(Y < 974245219737, "Year values above 974245219736 cause numerical overflow using 64-bit integers") - - // It is possible to adjust the year by a multiple of the cycle to have this function - // calculate correct values for the first day of Tishrei in proleptic years. However, - // this isn't a public function and the callers perform the translation before calling. - - let b = 31524 + 765433 * ((235 * Y - 234) / 19) - var d = b / 25920 - let e = b % 25920 - let f = 1 + (d % 7) - let g = ((7 * Y + 13) % 19) / 12 - let h = ((7 * Y + 6) % 19) / 12 - if e >= 19440 || (e >= 9924 && f == 3 && g == 0) || (e >= 16788 && f == 2 && g == 0 && h == 1) { - d = d + 1 - } - return d + (((d + 5) % 7) % 2) + 347997 - } - - /// Returns the year A.M. containing the specified Julian day number. - /// - /// - parameter J: A Julian day number. - /// - /// - returns: The year containing the specified Julian day number. - static func yearContaining(julianDayNumber J: JulianDayNumber) -> Int { - precondition(J >= epochJulianDayNumber, "Julian day number must be >= epoch") - precondition(J < 355839970905665, "Julian day numbers above 355839970905664 cause numerical overflow using 64-bit integers") - - let M = (25920 * (J - 347996)) / 765433 + 1 - var Y = 19 * (M / 235) + (19 * (M % 235) - 2) / 235 + 1 - let K = firstDayOfTishrei(year: Y) - if K > J { - Y = Y - 1 - } - return Y - } -} - -extension HebrewCalendar: JulianDayNumberConverting { - /// A date in the Hebrew calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The number of years in a cycle of the Hebrew calendar. - /// - /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. - static let calendarCycleYears = 689472 - - /// The number of days in a cycle of the Hebrew calendar. - /// - /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. - static let calendarCycleDays = 251827457 - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - if Y < 1 { - ΔcalendarCycles = (1 - Y) / calendarCycleYears + 1 - Y += ΔcalendarCycles * calendarCycleYears - } - - let a = firstDayOfTishrei(year: Y) - let b = firstDayOfTishrei(year: Y + 1) - let K = b - a - 352 - 27 * (((7 * Y + 13) % 19) / 12) - var J = a + A[K - 1][date.month - 1] + date.day - 1 - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * calendarCycleDays - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - if J < epochJulianDayNumber { - ΔcalendarCycles = (epochJulianDayNumber - J) / calendarCycleDays + 1 - J += ΔcalendarCycles * calendarCycleDays - } - - var Y = yearContaining(julianDayNumber: J) - let a = firstDayOfTishrei(year: Y) - let b = firstDayOfTishrei(year: Y + 1) - let K = b - a - 352 - 27 * (((7 * Y + 13) % 19) / 12) - let c = J - a + 1 - precondition(c >= 0) - let AK = A[K - 1] - let M = AK.lastIndex(where: {$0 < c})! + 1 - let D = c - AK[M - 1] - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * calendarCycleYears - } - - return (Y, M, D) - } - - /// The number of days preceding the first of the month in a year with characterization K. - /// - /// The array is indexed first by `K - 1` and the resultant array by `M - 1`. - static let A = [ - // A deficient common year. - [0, 30, 59, 88, 117, 147, 176, 206, 235, 265, 294, 324], - // A regular common year. - [0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325], - // An abundant common year. - [0, 30, 60, 90, 119, 149, 178, 208, 237, 267, 296, 326], - // A deficient leap year. - [0, 30, 59, 88, 117, 147, 177, 206, 236, 265, 295, 324, 354], - // A regular leap year. - [0, 30, 59, 89, 118, 148, 178, 207, 237, 266, 296, 325, 355], - // An abundant leap year. - [0, 30, 60, 90, 119, 149, 179, 208, 238, 267, 297, 326, 356], - ] -} diff --git a/Sources/JulianDayNumber/HebrewCalendar.swift b/Sources/JulianDayNumber/HebrewCalendar.swift index ec93be4..8ace8eb 100644 --- a/Sources/JulianDayNumber/HebrewCalendar.swift +++ b/Sources/JulianDayNumber/HebrewCalendar.swift @@ -208,3 +208,132 @@ public struct HebrewCalendar { return monthLengths[K - 1][M - 1] } } + +// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. + +extension HebrewCalendar { + /// Returns the Julian day number of the first day of Tishrei in the specified year. + /// + /// - attention: No validation check is performed on the year value. + /// + /// - parameter Y: A year A.M. + /// + /// - returns: The Julian day number of the first day of Tishrei in the specified year. + static func firstDayOfTishrei(year Y: Int) -> JulianDayNumber { + precondition(Y > 0, "First day of Tishrei calculations only valid for year numbers > 0") + precondition(Y < 974245219737, "Year values above 974245219736 cause numerical overflow using 64-bit integers") + + // It is possible to adjust the year by a multiple of the cycle to have this function + // calculate correct values for the first day of Tishrei in proleptic years. However, + // this isn't a public function and the callers perform the translation before calling. + + let b = 31524 + 765433 * ((235 * Y - 234) / 19) + var d = b / 25920 + let e = b % 25920 + let f = 1 + (d % 7) + let g = ((7 * Y + 13) % 19) / 12 + let h = ((7 * Y + 6) % 19) / 12 + if e >= 19440 || (e >= 9924 && f == 3 && g == 0) || (e >= 16788 && f == 2 && g == 0 && h == 1) { + d = d + 1 + } + return d + (((d + 5) % 7) % 2) + 347997 + } + + /// Returns the year A.M. containing the specified Julian day number. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The year containing the specified Julian day number. + static func yearContaining(julianDayNumber J: JulianDayNumber) -> Int { + precondition(J >= epochJulianDayNumber, "Julian day number must be >= epoch") + precondition(J < 355839970905665, "Julian day numbers above 355839970905664 cause numerical overflow using 64-bit integers") + + let M = (25920 * (J - 347996)) / 765433 + 1 + var Y = 19 * (M / 235) + (19 * (M % 235) - 2) / 235 + 1 + let K = firstDayOfTishrei(year: Y) + if K > J { + Y = Y - 1 + } + return Y + } +} + +extension HebrewCalendar: JulianDayNumberConverting { + /// A date in the Hebrew calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The number of years in a cycle of the Hebrew calendar. + /// + /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. + static let calendarCycleYears = 689472 + + /// The number of days in a cycle of the Hebrew calendar. + /// + /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. + static let calendarCycleDays = 251827457 + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if Y < 1 { + ΔcalendarCycles = (1 - Y) / calendarCycleYears + 1 + Y += ΔcalendarCycles * calendarCycleYears + } + + let a = firstDayOfTishrei(year: Y) + let b = firstDayOfTishrei(year: Y + 1) + let K = b - a - 352 - 27 * (((7 * Y + 13) % 19) / 12) + var J = a + A[K - 1][date.month - 1] + date.day - 1 + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * calendarCycleDays + } + + return J + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + var J = J + var ΔcalendarCycles = 0 + + if J < epochJulianDayNumber { + ΔcalendarCycles = (epochJulianDayNumber - J) / calendarCycleDays + 1 + J += ΔcalendarCycles * calendarCycleDays + } + + var Y = yearContaining(julianDayNumber: J) + let a = firstDayOfTishrei(year: Y) + let b = firstDayOfTishrei(year: Y + 1) + let K = b - a - 352 - 27 * (((7 * Y + 13) % 19) / 12) + let c = J - a + 1 + precondition(c >= 0) + let AK = A[K - 1] + let M = AK.lastIndex(where: {$0 < c})! + 1 + let D = c - AK[M - 1] + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * calendarCycleYears + } + + return (Y, M, D) + } + + /// The number of days preceding the first of the month in a year with characterization K. + /// + /// The array is indexed first by `K - 1` and the resultant array by `M - 1`. + static let A = [ + // A deficient common year. + [0, 30, 59, 88, 117, 147, 176, 206, 235, 265, 294, 324], + // A regular common year. + [0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325], + // An abundant common year. + [0, 30, 60, 90, 119, 149, 178, 208, 237, 267, 296, 326], + // A deficient leap year. + [0, 30, 59, 88, 117, 147, 177, 206, 236, 265, 295, 324, 354], + // A regular leap year. + [0, 30, 59, 89, 118, 148, 178, 207, 237, 266, 296, 325, 355], + // An abundant leap year. + [0, 30, 60, 90, 119, 149, 179, 208, 238, 267, 297, 326, 356], + ] +} diff --git a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift b/Sources/JulianDayNumber/IslamicCalendar+JDN.swift deleted file mode 100644 index a48e213..0000000 --- a/Sources/JulianDayNumber/IslamicCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension IslamicCalendar: JulianDayNumberConverting { - /// A date in the Islamic calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Islamic calendar is 19 common years of 354 days and 11 leap years of 355 days. - static let intercalatingCycle = (years: 30, days: 10631) - - /// The date for Julian day number zero in the proleptic Islamic calendar. - static let julianDayNumberZero = (year: -5498, month: 8, day: 16) - - /// Algorithm parameters for Islamic calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/IslamicCalendar.swift b/Sources/JulianDayNumber/IslamicCalendar.swift index 46618b0..cdbb2b6 100644 --- a/Sources/JulianDayNumber/IslamicCalendar.swift +++ b/Sources/JulianDayNumber/IslamicCalendar.swift @@ -97,3 +97,25 @@ public struct IslamicCalendar { } } } + +extension IslamicCalendar: JulianDayNumberConverting { + /// A date in the Islamic calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Islamic calendar is 19 common years of 354 days and 11 leap years of 355 days. + static let intercalatingCycle = (years: 30, days: 10631) + + /// The date for Julian day number zero in the proleptic Islamic calendar. + static let julianDayNumberZero = (year: -5498, month: 8, day: 16) + + /// Algorithm parameters for Islamic calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/JulianCalendar+JDN.swift b/Sources/JulianDayNumber/JulianCalendar+JDN.swift deleted file mode 100644 index eb7da56..0000000 --- a/Sources/JulianDayNumber/JulianCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension JulianCalendar: JulianDayNumberConverting { - /// A date in the Julian calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Julian calendar is 3 common years of 365 days and 1 leap year of 366 days. - static let intercalatingCycle = (years: 4, days: 1461) - - /// The date for Julian day number zero in the proleptic Julian calendar. - static let julianDayNumberZero = (year: -4712, month: 1, day: 1) - - /// Algorithm parameters for Julian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/JulianCalendar.swift b/Sources/JulianDayNumber/JulianCalendar.swift index 77bd034..69fbc80 100644 --- a/Sources/JulianDayNumber/JulianCalendar.swift +++ b/Sources/JulianDayNumber/JulianCalendar.swift @@ -153,3 +153,25 @@ public struct JulianCalendar { return (M, D) } } + +extension JulianCalendar: JulianDayNumberConverting { + /// A date in the Julian calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Julian calendar is 3 common years of 365 days and 1 leap year of 366 days. + static let intercalatingCycle = (years: 4, days: 1461) + + /// The date for Julian day number zero in the proleptic Julian calendar. + static let julianDayNumberZero = (year: -4712, month: 1, day: 1) + + /// Algorithm parameters for Julian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift b/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift deleted file mode 100644 index af23767..0000000 --- a/Sources/JulianDayNumber/KhwarizmianCalendar+JDN.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -extension KhwarizmianCalendar: JulianDayNumberConverting { - /// A date in the Khwarizmian calendar consists of a year, month, and day. - public typealias DateType = (year: Year, month: Month, day: Day) - - /// The intercalating cycle of the Khwarizmian calendar is 1 year of 365 days. - static let intercalatingCycle = (years: 1, days: 365) - - /// The date for Julian day number zero in the proleptic Khwarizmian calendar. - static let julianDayNumberZero = (year: -5348, month: 11, day: 18) - - /// Algorithm parameters for Khwarizmian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) - } -} diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar.swift b/Sources/JulianDayNumber/KhwarizmianCalendar.swift index f24fcee..24b0735 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar.swift @@ -78,3 +78,25 @@ public struct KhwarizmianCalendar { return monthLengths[M - 1] } } + +extension KhwarizmianCalendar: JulianDayNumberConverting { + /// A date in the Khwarizmian calendar consists of a year, month, and day. + public typealias DateType = (year: Year, month: Month, day: Day) + + /// The intercalating cycle of the Khwarizmian calendar is 1 year of 365 days. + static let intercalatingCycle = (years: 1, days: 365) + + /// The date for Julian day number zero in the proleptic Khwarizmian calendar. + static let julianDayNumberZero = (year: -5348, month: 11, day: 18) + + /// Algorithm parameters for Khwarizmian calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + } +} diff --git a/Sources/JulianDayNumber/SakaCalendar+JDN.swift b/Sources/JulianDayNumber/SakaCalendar+JDN.swift deleted file mode 100644 index 51a24c4..0000000 --- a/Sources/JulianDayNumber/SakaCalendar+JDN.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -extension SakaCalendar: JulianDayNumberConverting { - /// A date in the Śaka calendar consists of a year, month, and day. - public typealias DateType = (year: Int, month: Int, day: Int) - - /// The intercalating cycle of the Śaka calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic Śaka calendar. - static let julianDayNumberZero = (year: -4791, month: 9, day: 3) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - if date < julianDayNumberZero { - ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / intercalatingCycle.years + 1 - Y += ΔcalendarCycles * intercalatingCycle.years - } - - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j - let Z = f / 6 - var J = e + ((31 - Z) * f + 5 * Z) / u - J = J - (3 * ((g + A) / 100)) / 4 - C - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * intercalatingCycle.days - } - - return J - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / intercalatingCycle.days + 1 - J += ΔcalendarCycles * intercalatingCycle.days - } - - var f = J + j - f = f + (((4 * J + B) / 146097) * 3) / 4 + C - let e = r * f + v - let g = (e % p) / r - let X = g / 365 - let Z = g / 185 - X - let s = 31 - Z - let w = -5 * Z - let h = u * g + w - let D = (6 * X + (h % s)) / u + 1 - - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * intercalatingCycle.years - } - - return (Y, M, D) - } - - // Constants for Śaka calendar conversions - static let y = 4794 - static let j = 1348 - static let m = 1 - static let n = 12 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 1 - static let s = 31 - static let t = 0 - static let w = 0 - static let A = 184 - static let B = 274073 - static let C = -36 -} diff --git a/Sources/JulianDayNumber/SakaCalendar.swift b/Sources/JulianDayNumber/SakaCalendar.swift index 7470f3c..2b7618c 100644 --- a/Sources/JulianDayNumber/SakaCalendar.swift +++ b/Sources/JulianDayNumber/SakaCalendar.swift @@ -128,3 +128,88 @@ public struct SakaCalendar { } } } + +// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. + +extension SakaCalendar: JulianDayNumberConverting { + /// A date in the Śaka calendar consists of a year, month, and day. + public typealias DateType = (year: Int, month: Int, day: Int) + + /// The intercalating cycle of the Śaka calendar is 303 common years of 365 days and 97 leap years of 366 days. + static let intercalatingCycle = (years: 400, days: 146097) + + /// The date for Julian day number zero in the proleptic Śaka calendar. + static let julianDayNumberZero = (year: -4791, month: 9, day: 3) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if date < julianDayNumberZero { + ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / intercalatingCycle.years + 1 + Y += ΔcalendarCycles * intercalatingCycle.years + } + + let h = date.month - m + let g = Y + y - (n - h) / n + let f = (h - 1 + n) % n + let e = (p * g + q) / r + date.day - 1 - j + let Z = f / 6 + var J = e + ((31 - Z) * f + 5 * Z) / u + J = J - (3 * ((g + A) / 100)) / 4 - C + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * intercalatingCycle.days + } + + return J + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + var J = J + var ΔcalendarCycles = 0 + + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / intercalatingCycle.days + 1 + J += ΔcalendarCycles * intercalatingCycle.days + } + + var f = J + j + f = f + (((4 * J + B) / 146097) * 3) / 4 + C + let e = r * f + v + let g = (e % p) / r + let X = g / 365 + let Z = g / 185 - X + let s = 31 - Z + let w = -5 * Z + let h = u * g + w + let D = (6 * X + (h % s)) / u + 1 + + let M = ((h / s + m) % n) + 1 + var Y = e / p - y + (n + m - M) / n + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * intercalatingCycle.years + } + + return (Y, M, D) + } + + // Constants for Śaka calendar conversions + static let y = 4794 + static let j = 1348 + static let m = 1 + static let n = 12 + static let r = 4 + static let p = 1461 + static let q = 0 + static let v = 3 + static let u = 1 + static let s = 31 + static let t = 0 + static let w = 0 + static let A = 184 + static let B = 274073 + static let C = -36 +} From 90dfbc53c2bad3f8030767d1d6192f1492422bec Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 22:48:26 -0600 Subject: [PATCH 07/45] More consolidation --- .../JulianDayNumber/MayaCalendar+JDN.swift | 220 ------------------ Sources/JulianDayNumber/MayaCalendar.swift | 213 +++++++++++++++++ 2 files changed, 213 insertions(+), 220 deletions(-) delete mode 100644 Sources/JulianDayNumber/MayaCalendar+JDN.swift diff --git a/Sources/JulianDayNumber/MayaCalendar+JDN.swift b/Sources/JulianDayNumber/MayaCalendar+JDN.swift deleted file mode 100644 index 7503e38..0000000 --- a/Sources/JulianDayNumber/MayaCalendar+JDN.swift +++ /dev/null @@ -1,220 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -// Maya long count cycle lengths - -/// One uinal is composed of 20 kin. -let kinPerUinal = 20 -/// One tun is composed of 18 uinal. -let uinalPerTun = 18 -/// One katun is composed of 20 tun. -let tunPerKatun = 20 -/// One baktun is composed of 20 katun. -let katunPerBaktun = 20 -/// One pictun is composed of 20 baktun. -let baktunPerPictun = 20 -/// One calabtun is composed of 20 pictun. -let pictunPerCalabtun = 20 -/// One kinchiltun is composed of 20 calabtun. -let calabtunPerKinchiltun = 20 -/// One alautun is composed of 20 kinchiltun. -let kinchiltunPerAlautun = 20 - -extension MayaCalendar: JulianDayNumberConverting { - /// A long count in the Maya calendar. - public typealias DateType = (baktun: Baktun, katun: Katun, tun: Tun, uinal: Uinal, kin: Kin) - - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - julianDayNumberFromLongCount(baktun: date.baktun, katun: date.katun, tun: date.tun, uinal: date.uinal, kin: date.kin) - } - - public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - longCountFromJulianDayNumber(J) - } -} - -extension MayaCalendar { - /// Converts a Julian day number to a long count in the Maya calendar. - /// - /// - parameter J: A Julian day number. - /// - /// - returns: The long count corresponding to the specified Julian day number. - public static func longCountFromJulianDayNumber(_ J: JulianDayNumber) -> (/*alautun: Alautun, kinchiltun: Kinchiltun, calabtun: Calabtun, pictun: Pictun, */baktun: Baktun, katun: Katun, tun: Tun, uinal: Uinal, kin: Kin) { - let L = J - longCountEpochJulianDayNumber - -#if false - var alautun, kinchiltun, calabtun, pictun: Int -#endif - var baktun, katun, tun, uinal, kin: Int - - (uinal, kin) = L.quotientAndRemainder(dividingBy: kinPerUinal) - (tun, uinal) = uinal.quotientAndRemainder(dividingBy: uinalPerTun) - (katun, tun) = tun.quotientAndRemainder(dividingBy: tunPerKatun) - (baktun, katun) = katun.quotientAndRemainder(dividingBy: katunPerBaktun) -#if false - (pictun, baktun) = baktun.quotientAndRemainder(dividingBy: baktunPerPictun) - (calabtun, pictun) = pictun.quotientAndRemainder(dividingBy: pictunPerCalabtun) - (kinchiltun, calabtun) = calabtun.quotientAndRemainder(dividingBy: calabtunPerKinchiltun) - (alautun, kinchiltun) = kinchiltun.quotientAndRemainder(dividingBy: kinchiltunPerAlautun) -#endif - - if L < 0 { - if kin < 0 { - kin += kinPerUinal - uinal -= 1 - } - if uinal < 0 { - uinal += uinalPerTun - tun -= 1 - } - if tun < 0 { - tun += tunPerKatun - katun -= 1 - } - if katun < 0 { - katun += katunPerBaktun - baktun -= 1 - } -#if false - if baktun < 1 - baktunPerPictun { - baktun += baktunPerPictun - pictun -= 1 - } - if pictun < 1 - pictunPerCalabtun { - pictun += pictunPerCalabtun - calabtun -= 1 - } - if calabtun < 1 - calabtunPerKinchiltun { - calabtun += calabtunPerKinchiltun - kinchiltun -= 1 - } - if kinchiltun < 1 - kinchiltunPerAlautun { - kinchiltun += kinchiltunPerAlautun - alautun -= 1 - } -#endif - } - - return (/*alautun, kinchiltun, calabtun, pictun, */baktun, katun, tun, uinal, kin) - } - - /// Converts a long count in the Maya calendar to a Julian day number. - /// - /// - note: No validation checks are performed on the cycle values. - /// - /// - parameter alautun: An alautun number. - /// - parameter kinchiltun: A kinchiltun number. - /// - parameter calabtun: A calabtun number. - /// - parameter pictun: A pictun number. - /// - parameter baktun: A baktun number. - /// - parameter katun: A katun number. - /// - parameter tun: A tun number. - /// - parameter uinal: A uinal number. - /// - parameter kin: A kin number. - /// - /// - returns: The Julian day number corresponding to the specified long count. - public static func julianDayNumberFromLongCount(alautun: Alautun = 0, kinchiltun: Kinchiltun = 0, calabtun: Calabtun = 0, pictun: Pictun = 0, baktun: Baktun, katun: Katun, tun: Tun, uinal: Uinal, kin: Kin) -> JulianDayNumber { - longCountEpochJulianDayNumber + (((((((alautun * kinchiltunPerAlautun + kinchiltun) * calabtunPerKinchiltun + calabtun) * pictunPerCalabtun + pictun) * baktunPerPictun + baktun) * katunPerBaktun + katun) * tunPerKatun + tun) * uinalPerTun + uinal) * kinPerUinal + kin - } -} - -extension MayaCalendar { - /// Converts a Julian day number to a Calendar Round in the Maya calendar. - /// - /// - note: A Calendar Round corresponding to a Julian day number - /// can also be represented by the same Julian day number with multiples - /// of 18,980 days added or subtracted. - /// - /// - parameter J: A Julian day number. - /// - /// - returns: The Calendar Round corresponding to the specified Julian day number. - public static func calendarRoundFromJulianDayNumber(_ J: JulianDayNumber) -> (number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth) { - let T = J - tzolkinEpochJulianDayNumber - let H = J - haabEpochJulianDayNumber - - let (number, name) = (T % 13 + 1, T % 20) - let (month, day) = (H % 365).quotientAndRemainder(dividingBy: 20) - - return (number, name + 1, day, month + 1) - } - - /// Returns the most recent Julian day number for a Calendar Round in the Maya calendar occurring before a Julian day number. - /// - /// - important: Not all combinations of Tzolkʼin and Haabʼ dates are valid. - /// - /// - parameter number: A Tzolkʼin number. - /// - parameter name: A Tzolkʼin day name. - /// - parameter day: A Haabʼ day. - /// - parameter month: A Haabʼ month. - /// - parameter J0: A Julian day number to anchor the Calendar Round. - /// - /// - returns: The most recent Julian day number corresponding to the specified Calendar Round occurring before the specified Julian day number or `nil` if none. - public static func julianDayNumberFromCalendarRound(number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth, before J0: JulianDayNumber) -> JulianDayNumber? { - guard let J = julianDayNumberFromCalendarRound(number: number, name: name, day: day, month: month) else { - return nil - } - return J0 + (J - J0) % 18980 - 18980 - } - - /// Returns the least recent Julian day number for a Calendar Round in the Maya calendar occurring on or after a Julian day number. - /// - /// - important: Not all combinations of Tzolkʼin and Haabʼ dates are valid. - /// - /// - parameter number: A Tzolkʼin number. - /// - parameter name: A Tzolkʼin day name. - /// - parameter day: A Haabʼ day. - /// - parameter month: A Haabʼ month. - /// - parameter J0: A Julian day number to anchor the Calendar Round. - /// - /// - returns: The least recent Julian day number corresponding to the specified Calendar Round occurring on or after the specified Julian day number or `nil` if none. - public static func julianDayNumberFromCalendarRound(number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth, onOrAfter J0: JulianDayNumber = longCountEpochJulianDayNumber) -> JulianDayNumber? { - guard let J = julianDayNumberFromCalendarRound(number: number, name: name, day: day, month: month) else { - return nil - } - return J0 - (J0 - J) % 18980 //+ 18980 - } - - /// Returns a possible Julian day number for a Calendar Round in the Maya calendar. - /// - /// - parameter number: A Tzolkʼin number. - /// - parameter name: A Tzolkʼin day name. - /// - parameter day: A Haabʼ day. - /// - parameter month: A Haabʼ month. - /// - /// - returns: A possible Julian day number corresponding to the specified Calendar Round or `nil` if none. - static func julianDayNumberFromCalendarRound(number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth) -> JulianDayNumber? { - // The number of days into the Tzolkʼin cycle - let T = (40 * number + 221 * name - 1) % 260 - - // The number of days into the Haabʼ cycle - let H = 20 * (month - 1) + day - - // Not all combinations of H and T are valid - guard (H - T) % 5 == 4 else { - return nil - } - - return (365 * T - 364 * H + 7600) % 18980 - } -} - -extension MayaCalendar { - /// Returns the Lord of the Night for a given uinal and kin. - /// - /// The Lord of the Night is a nine-day cycle conventionally labeled G1 through G9. - /// - /// The Lord of the Night at the long count epoch was G9. - /// - /// - parameter uinal: A uinal number. - /// - parameter kin: A kin number. - /// - /// - returns: The Lord of the Night corresponding to the specified uinal and kin. - public static func lordOfTheNightFrom(uinal: Uinal, kin: Kin) -> Int { - (20 * uinal + kin + 8) % 9 + 1 - } -} diff --git a/Sources/JulianDayNumber/MayaCalendar.swift b/Sources/JulianDayNumber/MayaCalendar.swift index aeb246e..cc2da47 100644 --- a/Sources/JulianDayNumber/MayaCalendar.swift +++ b/Sources/JulianDayNumber/MayaCalendar.swift @@ -136,3 +136,216 @@ public struct MayaCalendar { /// A Haabʼ month from `1` to `19`. public typealias HaabMonth = Int } + +extension MayaCalendar: JulianDayNumberConverting { + /// A long count in the Maya calendar. + public typealias DateType = (baktun: Baktun, katun: Katun, tun: Tun, uinal: Uinal, kin: Kin) + + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { + julianDayNumberFromLongCount(baktun: date.baktun, katun: date.katun, tun: date.tun, uinal: date.uinal, kin: date.kin) + } + + public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { + longCountFromJulianDayNumber(J) + } +} + +extension MayaCalendar { + // Maya long count cycle lengths + + /// One uinal is composed of 20 kin. + static let kinPerUinal = 20 + /// One tun is composed of 18 uinal. + static let uinalPerTun = 18 + /// One katun is composed of 20 tun. + static let tunPerKatun = 20 + /// One baktun is composed of 20 katun. + static let katunPerBaktun = 20 + /// One pictun is composed of 20 baktun. + static let baktunPerPictun = 20 + /// One calabtun is composed of 20 pictun. + static let pictunPerCalabtun = 20 + /// One kinchiltun is composed of 20 calabtun. + static let calabtunPerKinchiltun = 20 + /// One alautun is composed of 20 kinchiltun. + static let kinchiltunPerAlautun = 20 + + /// Converts a Julian day number to a long count in the Maya calendar. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The long count corresponding to the specified Julian day number. + public static func longCountFromJulianDayNumber(_ J: JulianDayNumber) -> (/*alautun: Alautun, kinchiltun: Kinchiltun, calabtun: Calabtun, pictun: Pictun, */baktun: Baktun, katun: Katun, tun: Tun, uinal: Uinal, kin: Kin) { + let L = J - longCountEpochJulianDayNumber + +#if false + var alautun, kinchiltun, calabtun, pictun: Int +#endif + var baktun, katun, tun, uinal, kin: Int + + (uinal, kin) = L.quotientAndRemainder(dividingBy: kinPerUinal) + (tun, uinal) = uinal.quotientAndRemainder(dividingBy: uinalPerTun) + (katun, tun) = tun.quotientAndRemainder(dividingBy: tunPerKatun) + (baktun, katun) = katun.quotientAndRemainder(dividingBy: katunPerBaktun) +#if false + (pictun, baktun) = baktun.quotientAndRemainder(dividingBy: baktunPerPictun) + (calabtun, pictun) = pictun.quotientAndRemainder(dividingBy: pictunPerCalabtun) + (kinchiltun, calabtun) = calabtun.quotientAndRemainder(dividingBy: calabtunPerKinchiltun) + (alautun, kinchiltun) = kinchiltun.quotientAndRemainder(dividingBy: kinchiltunPerAlautun) +#endif + + if L < 0 { + if kin < 0 { + kin += kinPerUinal + uinal -= 1 + } + if uinal < 0 { + uinal += uinalPerTun + tun -= 1 + } + if tun < 0 { + tun += tunPerKatun + katun -= 1 + } + if katun < 0 { + katun += katunPerBaktun + baktun -= 1 + } +#if false + if baktun < 1 - baktunPerPictun { + baktun += baktunPerPictun + pictun -= 1 + } + if pictun < 1 - pictunPerCalabtun { + pictun += pictunPerCalabtun + calabtun -= 1 + } + if calabtun < 1 - calabtunPerKinchiltun { + calabtun += calabtunPerKinchiltun + kinchiltun -= 1 + } + if kinchiltun < 1 - kinchiltunPerAlautun { + kinchiltun += kinchiltunPerAlautun + alautun -= 1 + } +#endif + } + + return (/*alautun, kinchiltun, calabtun, pictun, */baktun, katun, tun, uinal, kin) + } + + /// Converts a long count in the Maya calendar to a Julian day number. + /// + /// - note: No validation checks are performed on the cycle values. + /// + /// - parameter alautun: An alautun number. + /// - parameter kinchiltun: A kinchiltun number. + /// - parameter calabtun: A calabtun number. + /// - parameter pictun: A pictun number. + /// - parameter baktun: A baktun number. + /// - parameter katun: A katun number. + /// - parameter tun: A tun number. + /// - parameter uinal: A uinal number. + /// - parameter kin: A kin number. + /// + /// - returns: The Julian day number corresponding to the specified long count. + public static func julianDayNumberFromLongCount(alautun: Alautun = 0, kinchiltun: Kinchiltun = 0, calabtun: Calabtun = 0, pictun: Pictun = 0, baktun: Baktun, katun: Katun, tun: Tun, uinal: Uinal, kin: Kin) -> JulianDayNumber { + longCountEpochJulianDayNumber + (((((((alautun * kinchiltunPerAlautun + kinchiltun) * calabtunPerKinchiltun + calabtun) * pictunPerCalabtun + pictun) * baktunPerPictun + baktun) * katunPerBaktun + katun) * tunPerKatun + tun) * uinalPerTun + uinal) * kinPerUinal + kin + } +} + +extension MayaCalendar { + /// Converts a Julian day number to a Calendar Round in the Maya calendar. + /// + /// - note: A Calendar Round corresponding to a Julian day number + /// can also be represented by the same Julian day number with multiples + /// of 18,980 days added or subtracted. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The Calendar Round corresponding to the specified Julian day number. + public static func calendarRoundFromJulianDayNumber(_ J: JulianDayNumber) -> (number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth) { + let T = J - tzolkinEpochJulianDayNumber + let H = J - haabEpochJulianDayNumber + + let (number, name) = (T % 13 + 1, T % 20) + let (month, day) = (H % 365).quotientAndRemainder(dividingBy: 20) + + return (number, name + 1, day, month + 1) + } + + /// Returns the most recent Julian day number for a Calendar Round in the Maya calendar occurring before a Julian day number. + /// + /// - important: Not all combinations of Tzolkʼin and Haabʼ dates are valid. + /// + /// - parameter number: A Tzolkʼin number. + /// - parameter name: A Tzolkʼin day name. + /// - parameter day: A Haabʼ day. + /// - parameter month: A Haabʼ month. + /// - parameter J0: A Julian day number to anchor the Calendar Round. + /// + /// - returns: The most recent Julian day number corresponding to the specified Calendar Round occurring before the specified Julian day number or `nil` if none. + public static func julianDayNumberFromCalendarRound(number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth, before J0: JulianDayNumber) -> JulianDayNumber? { + guard let J = julianDayNumberFromCalendarRound(number: number, name: name, day: day, month: month) else { + return nil + } + return J0 + (J - J0) % 18980 - 18980 + } + + /// Returns the least recent Julian day number for a Calendar Round in the Maya calendar occurring on or after a Julian day number. + /// + /// - important: Not all combinations of Tzolkʼin and Haabʼ dates are valid. + /// + /// - parameter number: A Tzolkʼin number. + /// - parameter name: A Tzolkʼin day name. + /// - parameter day: A Haabʼ day. + /// - parameter month: A Haabʼ month. + /// - parameter J0: A Julian day number to anchor the Calendar Round. + /// + /// - returns: The least recent Julian day number corresponding to the specified Calendar Round occurring on or after the specified Julian day number or `nil` if none. + public static func julianDayNumberFromCalendarRound(number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth, onOrAfter J0: JulianDayNumber = longCountEpochJulianDayNumber) -> JulianDayNumber? { + guard let J = julianDayNumberFromCalendarRound(number: number, name: name, day: day, month: month) else { + return nil + } + return J0 - (J0 - J) % 18980 //+ 18980 + } + + /// Returns a possible Julian day number for a Calendar Round in the Maya calendar. + /// + /// - parameter number: A Tzolkʼin number. + /// - parameter name: A Tzolkʼin day name. + /// - parameter day: A Haabʼ day. + /// - parameter month: A Haabʼ month. + /// + /// - returns: A possible Julian day number corresponding to the specified Calendar Round or `nil` if none. + static func julianDayNumberFromCalendarRound(number: TzolkinNumber, name: TzolkinDayName, day: HaabDay, month: HaabMonth) -> JulianDayNumber? { + // The number of days into the Tzolkʼin cycle + let T = (40 * number + 221 * name - 1) % 260 + + // The number of days into the Haabʼ cycle + let H = 20 * (month - 1) + day + + // Not all combinations of H and T are valid + guard (H - T) % 5 == 4 else { + return nil + } + + return (365 * T - 364 * H + 7600) % 18980 + } +} + +extension MayaCalendar { + /// Returns the Lord of the Night for a given uinal and kin. + /// + /// The Lord of the Night is a nine-day cycle conventionally labeled G1 through G9. + /// + /// The Lord of the Night at the long count epoch was G9. + /// + /// - parameter uinal: A uinal number. + /// - parameter kin: A kin number. + /// + /// - returns: The Lord of the Night corresponding to the specified uinal and kin. + public static func lordOfTheNightFrom(uinal: Uinal, kin: Kin) -> Int { + (20 * uinal + kin + 8) % 9 + 1 + } +} From 36f9a127e08a3f4e85c1fb15ab4902f73c708c82 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 22:51:45 -0600 Subject: [PATCH 08/45] Add documentation --- Sources/JulianDayNumber/JDN.swift | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Sources/JulianDayNumber/JDN.swift b/Sources/JulianDayNumber/JDN.swift index 0e8cdc5..02547b7 100644 --- a/Sources/JulianDayNumber/JDN.swift +++ b/Sources/JulianDayNumber/JDN.swift @@ -154,7 +154,17 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve return (Y, M, D) } - +/// Converts a date to a Julian day number using the specified conversion parameters and returns the result. +/// +/// - important: No validation checks are performed on the date values. +/// +/// - parameter date: A date to convert. +/// - parameter parameters: Parameters for the conversion algorithm. +/// - parameter gregorianIntercalatingParameters: Parameters for Gregorian-type intercalating. +/// - parameter jdnZero: The date for which the Julian day number is zero. +/// - parameter intercalatingCycle: The calendar's intercalating cycle. +/// +/// - returns: The Julian day number corresponding to the specified date. func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters, jdnZero: YearMonthDay, intercalatingCycle: IntercalatingCycle) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 @@ -178,6 +188,14 @@ func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConve return J } +/// Converts a Julian day number to a date and returns the result. +/// +/// - parameter J: A Julian day number. +/// - parameter parameters: Parameters for the conversion algorithm. +/// - parameter gregorianIntercalatingParameters: Parameters for Gregorian-type intercalating. +/// - parameter intercalatingCycle: The calendar's intercalating cycle. +/// +/// - returns: The date corresponding to the specified Julian day number. func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters, intercalatingCycle: IntercalatingCycle) -> YearMonthDay { var J = J var ΔcalendarCycles = 0 From 65bae4af200ea6205f28895d9c5b97f62a2ca96c Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 22:52:26 -0600 Subject: [PATCH 09/45] Rename JDN.swift --- .../{JDN.swift => JulianDayNumberConverting.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Sources/JulianDayNumber/{JDN.swift => JulianDayNumberConverting.swift} (100%) diff --git a/Sources/JulianDayNumber/JDN.swift b/Sources/JulianDayNumber/JulianDayNumberConverting.swift similarity index 100% rename from Sources/JulianDayNumber/JDN.swift rename to Sources/JulianDayNumber/JulianDayNumberConverting.swift From 0eea744344179d60e12feaf7f140adaeb49dcc44 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 22:54:55 -0600 Subject: [PATCH 10/45] Consolidate JD into JulianDayNumberConverting --- Sources/JulianDayNumber/JD.swift | 93 ------------------- .../JulianDayNumberConverting.swift | 88 ++++++++++++++++++ 2 files changed, 88 insertions(+), 93 deletions(-) delete mode 100644 Sources/JulianDayNumber/JD.swift diff --git a/Sources/JulianDayNumber/JD.swift b/Sources/JulianDayNumber/JD.swift deleted file mode 100644 index b76c5c6..0000000 --- a/Sources/JulianDayNumber/JD.swift +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright © 2021-2023 Stephen F. Booth -// Part of https://github.com/sbooth/JulianDayNumber -// MIT license -// - -import Foundation - -/// A Julian date. -/// -/// The Julian date (JD) is the Julian day number (JDN) plus the fraction of a day since the preceding noon in Universal Time. -/// Julian dates are expressed as a JDN with a decimal fraction added. -/// -/// - seealso: [Julian day](https://en.wikipedia.org/wiki/Julian_day) -public typealias JulianDate = Double - -extension JulianDayNumberConverting where DateType == (year: Int, month: Int, day: Int) { - /// Converts the specified year, month, day, hour, minute, and second to a Julian date and returns the result. - /// - /// - important: No validation checks are performed on the date values. - /// - /// - parameter Y: A year number. - /// - parameter M: A month number. - /// - parameter D: A day number. - /// - parameter h: An hour number between `0` and `23`. - /// - parameter m: A minute number between `0` and `59`. - /// - parameter s: A second number between `0` and `59`. - /// - /// - returns: The Julian date corresponding to the specified year, month, day, hour, minute, and second. - public static func julianDateFrom(year Y: Int, month M: Int, day D: Int, hour h: Int = 0, minute m: Int = 0, second s: Double = 0) -> JulianDate { - julianDateFrom(year: Y, month: M, day: Double(D) + fractionalDayFrom(hour: h, minute: m, second: s)) - } - - /// Converts the specified year, month, and decimal day to a Julian date and returns the result. - /// - /// - important: No validation checks are performed on the date values. - /// - /// - parameter Y: A year number. - /// - parameter M: A month number. - /// - parameter D: A day number. - /// - /// - returns: The Julian date corresponding to the specified year, month, and decimal day. - public static func julianDateFrom(year Y: Int, month M: Int, day D: Double) -> JulianDate { - let (day, dayFraction) = modf(D) - return Double(julianDayNumberFrom(year: Y, month: M, day: Int(day))) - 0.5 + dayFraction - } - - /// Converts the specified Julian date to a year, month, day, hour, minute, and second and returns the result. - /// - /// - parameter julianDate: A Julian date. - /// - /// - returns: The year, month, day, hour, minute, and second corresponding to the specified Julian date. - public static func dateAndTimeFromJulianDate(_ julianDate: JulianDate) -> (year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Double) { - let julianDatePlus12Hours = julianDate + 0.5 - let J = Int(julianDatePlus12Hours.rounded(.down)) - let (Y, M, D) = dateFromJulianDayNumber(J) - var (_, dayFraction) = modf(julianDatePlus12Hours) - if dayFraction < 0 { - dayFraction += 1 - } - let (h, m, s) = timeFromFractionalDay(dayFraction) - return (Y, M, D, h, m, s) - } -} - -// MARK: - Internal Functions - -/// Converts an hour, minute, and second to a decimal fractional day and returns the result. -/// -/// This function assumes a day is exactly 24 hours, an hour is exactly 60 minutes, and a minute is exactly 60 seconds. -/// -/// - parameter h: An hour number between `0` and `23`. -/// - parameter m: A minute number between `0` and `59`. -/// - parameter s: A second number between `0` and `59`. -/// -/// - returns: The decimal fractional day for the specified hour, minute, and second. -func fractionalDayFrom(hour h: Int, minute m: Int, second s: Double) -> Double { - (Double(h) / 24) + (Double(m) / 1440) + (s / 86400) -} - -/// Converts a decimal fractional day to an hour, minute, and second and returns the result. -/// -/// This function assumes a day is exactly 24 hours, an hour is exactly 60 minutes, and a minute is exactly 60 seconds. -/// -/// - parameter fractionalDay: A decimal fractional day in the half-open interval `[0,1)`. -/// -/// - returns: The hour, minute, and second for the specified decimal fractional day. -func timeFromFractionalDay(_ fractionalDay: Double) -> (hour: Int, minute: Int, second: Double) { - let (hour, hourFraction) = modf(fractionalDay * 24) - let (minute, minuteFraction) = modf(hourFraction * 60) - let second = minuteFraction * 60 - return (Int(hour), Int(minute), second) -} diff --git a/Sources/JulianDayNumber/JulianDayNumberConverting.swift b/Sources/JulianDayNumber/JulianDayNumberConverting.swift index 02547b7..45eea07 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverting.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverting.swift @@ -223,3 +223,91 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve return (Y, M, D) } + +// MARK: - Julian Date + +/// A Julian date. +/// +/// The Julian date (JD) is the Julian day number (JDN) plus the fraction of a day since the preceding noon in Universal Time. +/// Julian dates are expressed as a JDN with a decimal fraction added. +/// +/// - seealso: [Julian day](https://en.wikipedia.org/wiki/Julian_day) +public typealias JulianDate = Double + +extension JulianDayNumberConverting where DateType == (year: Int, month: Int, day: Int) { + /// Converts the specified year, month, day, hour, minute, and second to a Julian date and returns the result. + /// + /// - important: No validation checks are performed on the date values. + /// + /// - parameter Y: A year number. + /// - parameter M: A month number. + /// - parameter D: A day number. + /// - parameter h: An hour number between `0` and `23`. + /// - parameter m: A minute number between `0` and `59`. + /// - parameter s: A second number between `0` and `59`. + /// + /// - returns: The Julian date corresponding to the specified year, month, day, hour, minute, and second. + public static func julianDateFrom(year Y: Int, month M: Int, day D: Int, hour h: Int = 0, minute m: Int = 0, second s: Double = 0) -> JulianDate { + julianDateFrom(year: Y, month: M, day: Double(D) + fractionalDayFrom(hour: h, minute: m, second: s)) + } + + /// Converts the specified year, month, and decimal day to a Julian date and returns the result. + /// + /// - important: No validation checks are performed on the date values. + /// + /// - parameter Y: A year number. + /// - parameter M: A month number. + /// - parameter D: A day number. + /// + /// - returns: The Julian date corresponding to the specified year, month, and decimal day. + public static func julianDateFrom(year Y: Int, month M: Int, day D: Double) -> JulianDate { + let (day, dayFraction) = modf(D) + return Double(julianDayNumberFrom(year: Y, month: M, day: Int(day))) - 0.5 + dayFraction + } + + /// Converts the specified Julian date to a year, month, day, hour, minute, and second and returns the result. + /// + /// - parameter julianDate: A Julian date. + /// + /// - returns: The year, month, day, hour, minute, and second corresponding to the specified Julian date. + public static func dateAndTimeFromJulianDate(_ julianDate: JulianDate) -> (year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Double) { + let julianDatePlus12Hours = julianDate + 0.5 + let J = Int(julianDatePlus12Hours.rounded(.down)) + let (Y, M, D) = dateFromJulianDayNumber(J) + var (_, dayFraction) = modf(julianDatePlus12Hours) + if dayFraction < 0 { + dayFraction += 1 + } + let (h, m, s) = timeFromFractionalDay(dayFraction) + return (Y, M, D, h, m, s) + } +} + +// MARK: Internal Functions + +/// Converts an hour, minute, and second to a decimal fractional day and returns the result. +/// +/// This function assumes a day is exactly 24 hours, an hour is exactly 60 minutes, and a minute is exactly 60 seconds. +/// +/// - parameter h: An hour number between `0` and `23`. +/// - parameter m: A minute number between `0` and `59`. +/// - parameter s: A second number between `0` and `59`. +/// +/// - returns: The decimal fractional day for the specified hour, minute, and second. +func fractionalDayFrom(hour h: Int, minute m: Int, second s: Double) -> Double { + (Double(h) / 24) + (Double(m) / 1440) + (s / 86400) +} + +/// Converts a decimal fractional day to an hour, minute, and second and returns the result. +/// +/// This function assumes a day is exactly 24 hours, an hour is exactly 60 minutes, and a minute is exactly 60 seconds. +/// +/// - parameter fractionalDay: A decimal fractional day in the half-open interval `[0,1)`. +/// +/// - returns: The hour, minute, and second for the specified decimal fractional day. +func timeFromFractionalDay(_ fractionalDay: Double) -> (hour: Int, minute: Int, second: Double) { + let (hour, hourFraction) = modf(fractionalDay * 24) + let (minute, minuteFraction) = modf(hourFraction * 60) + let second = minuteFraction * 60 + return (Int(hour), Int(minute), second) +} From 8a613ebd4d9ecdeb9aa7682f44fab9dce12a963d Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 23:09:54 -0600 Subject: [PATCH 11/45] Remove unneeded intercalating cycle --- .../JulianDayNumber/ArmenianCalendar.swift | 7 ++---- Sources/JulianDayNumber/CopticCalendar.swift | 7 ++---- .../JulianDayNumber/EgyptianCalendar.swift | 7 ++---- .../JulianDayNumber/EthiopianCalendar.swift | 7 ++---- Sources/JulianDayNumber/IslamicCalendar.swift | 7 ++---- Sources/JulianDayNumber/JulianCalendar.swift | 7 ++---- .../JulianDayNumberConverting.swift | 22 ++++++++++--------- .../JulianDayNumber/KhwarizmianCalendar.swift | 7 ++---- 8 files changed, 26 insertions(+), 45 deletions(-) diff --git a/Sources/JulianDayNumber/ArmenianCalendar.swift b/Sources/JulianDayNumber/ArmenianCalendar.swift index acb982c..b077806 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar.swift @@ -83,9 +83,6 @@ extension ArmenianCalendar: JulianDayNumberConverting { /// A date in the Armenian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Armenian calendar is 1 year of 365 days. - static let intercalatingCycle = (years: 1, days: 365) - /// The date for Julian day number zero in the proleptic Armenian calendar. static let julianDayNumberZero = (year: -5268, month: 11, day: 18) @@ -93,10 +90,10 @@ extension ArmenianCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } diff --git a/Sources/JulianDayNumber/CopticCalendar.swift b/Sources/JulianDayNumber/CopticCalendar.swift index 6bc9c65..5e63104 100644 --- a/Sources/JulianDayNumber/CopticCalendar.swift +++ b/Sources/JulianDayNumber/CopticCalendar.swift @@ -100,9 +100,6 @@ extension CopticCalendar: JulianDayNumberConverting { /// A date in the Coptic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Coptic calendar is 3 common years of 365 days and 1 leap year of 366 days. - static let intercalatingCycle = (years: 4, days: 1461) - /// The date for Julian day number zero in the proleptic Coptic calendar. static let julianDayNumberZero = (year: -4996, month: 5, day: 5) @@ -110,10 +107,10 @@ extension CopticCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } diff --git a/Sources/JulianDayNumber/EgyptianCalendar.swift b/Sources/JulianDayNumber/EgyptianCalendar.swift index a46567b..80018f1 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar.swift @@ -84,9 +84,6 @@ extension EgyptianCalendar: JulianDayNumberConverting { /// A date in the Egyptian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Egyptian calendar is 1 year of 365 days. - static let intercalatingCycle = (years: 1, days: 365) - /// The date for Julian day number zero in the proleptic Egyptian calendar. static let julianDayNumberZero = (year: -3968, month: 2, day: 2) @@ -94,10 +91,10 @@ extension EgyptianCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } diff --git a/Sources/JulianDayNumber/EthiopianCalendar.swift b/Sources/JulianDayNumber/EthiopianCalendar.swift index ab265b7..b5134c5 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar.swift @@ -100,9 +100,6 @@ extension EthiopianCalendar: JulianDayNumberConverting { /// A date in the Ethiopian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Ethiopian calendar is 3 common years of 365 days and 1 leap year of 366 days. - static let intercalatingCycle = (years: 4, days: 1461) - /// The date for Julian day number zero in the proleptic Ethiopian calendar. static let julianDayNumberZero = (year: -4720, month: 5, day: 5) @@ -110,10 +107,10 @@ extension EthiopianCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } diff --git a/Sources/JulianDayNumber/IslamicCalendar.swift b/Sources/JulianDayNumber/IslamicCalendar.swift index cdbb2b6..109aeef 100644 --- a/Sources/JulianDayNumber/IslamicCalendar.swift +++ b/Sources/JulianDayNumber/IslamicCalendar.swift @@ -102,9 +102,6 @@ extension IslamicCalendar: JulianDayNumberConverting { /// A date in the Islamic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Islamic calendar is 19 common years of 354 days and 11 leap years of 355 days. - static let intercalatingCycle = (years: 30, days: 10631) - /// The date for Julian day number zero in the proleptic Islamic calendar. static let julianDayNumberZero = (year: -5498, month: 8, day: 16) @@ -112,10 +109,10 @@ extension IslamicCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } diff --git a/Sources/JulianDayNumber/JulianCalendar.swift b/Sources/JulianDayNumber/JulianCalendar.swift index 69fbc80..5e24e87 100644 --- a/Sources/JulianDayNumber/JulianCalendar.swift +++ b/Sources/JulianDayNumber/JulianCalendar.swift @@ -158,9 +158,6 @@ extension JulianCalendar: JulianDayNumberConverting { /// A date in the Julian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Julian calendar is 3 common years of 365 days and 1 leap year of 366 days. - static let intercalatingCycle = (years: 4, days: 1461) - /// The date for Julian day number zero in the proleptic Julian calendar. static let julianDayNumberZero = (year: -4712, month: 1, day: 1) @@ -168,10 +165,10 @@ extension JulianCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } diff --git a/Sources/JulianDayNumber/JulianDayNumberConverting.swift b/Sources/JulianDayNumber/JulianDayNumberConverting.swift index 45eea07..c8549a7 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverting.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverting.swift @@ -61,9 +61,13 @@ extension JulianDayNumberConverting where DateType == (year: Int, month: Int, da struct JDNConversionParameters { let y: Int let j: Int + /// The month number which corresponds to month zero in the computational calendar. let m: Int + /// The number of months in a year (counting any epagonomai as an extra month). let n: Int + /// The number of years in an intercalation cycle. let r: Int + /// The number of days in an intercalation cycle. let p: Int let q: Int let v: Int @@ -93,16 +97,15 @@ typealias YearMonthDay = (year: Int, month: Int, day: Int) /// - parameter date: A date to convert. /// - parameter parameters: Parameters for the conversion algorithm. /// - parameter jdnZero: The date for which the Julian day number is zero. -/// - parameter intercalatingCycle: The calendar's intercalating cycle. /// /// - returns: The Julian day number corresponding to the specified date. -func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, jdnZero: YearMonthDay, intercalatingCycle: IntercalatingCycle) -> JulianDayNumber { +func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, jdnZero: YearMonthDay) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 if date < jdnZero { - ΔcalendarCycles = (jdnZero.year - Y - 1) / intercalatingCycle.years + 1 - Y += ΔcalendarCycles * intercalatingCycle.years + ΔcalendarCycles = (jdnZero.year - Y - 1) / parameters.r + 1 + Y += ΔcalendarCycles * parameters.r } let h = date.month - parameters.m @@ -112,7 +115,7 @@ func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConve var J = e + (parameters.s * f + parameters.t) / parameters.u if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * intercalatingCycle.days + J -= ΔcalendarCycles * parameters.p } return J @@ -122,10 +125,9 @@ func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConve /// /// - parameter J: A Julian day number. /// - parameter parameters: Parameters for the conversion algorithm. -/// - parameter intercalatingCycle: The calendar's intercalating cycle. /// /// - returns: The date corresponding to the specified Julian day number. -func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, intercalatingCycle: IntercalatingCycle) -> YearMonthDay { +func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters) -> YearMonthDay { // precondition(J < Int.max - 1) var J = J @@ -133,8 +135,8 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve // Richards' algorithm is only valid for positive JDNs. if J < 0 { - ΔcalendarCycles = -J / intercalatingCycle.days + 1 - J += ΔcalendarCycles * intercalatingCycle.days + ΔcalendarCycles = -J / parameters.p + 1 + J += ΔcalendarCycles * parameters.p } precondition(J <= Int.max - parameters.j, "Julian day number too large") @@ -148,7 +150,7 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve var Y = e / parameters.p - parameters.y + (parameters.n + parameters.m - M) / parameters.n if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * intercalatingCycle.years + Y -= ΔcalendarCycles * parameters.r } return (Y, M, D) diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar.swift b/Sources/JulianDayNumber/KhwarizmianCalendar.swift index 24b0735..1ca3c82 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar.swift @@ -83,9 +83,6 @@ extension KhwarizmianCalendar: JulianDayNumberConverting { /// A date in the Khwarizmian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Khwarizmian calendar is 1 year of 365 days. - static let intercalatingCycle = (years: 1, days: 365) - /// The date for Julian day number zero in the proleptic Khwarizmian calendar. static let julianDayNumberZero = (year: -5348, month: 11, day: 18) @@ -93,10 +90,10 @@ extension KhwarizmianCalendar: JulianDayNumberConverting { static let conversionParameters = JDNConversionParameters(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters) } } From decc92952eeaa987b1d2227f887fccbd992b1208 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Tue, 14 Nov 2023 23:36:45 -0600 Subject: [PATCH 12/45] Use conversion params already present --- Sources/JulianDayNumber/ArmenianCalendar.swift | 5 +---- Sources/JulianDayNumber/CopticCalendar.swift | 5 +---- Sources/JulianDayNumber/EgyptianCalendar.swift | 5 +---- Sources/JulianDayNumber/EthiopianCalendar.swift | 5 +---- Sources/JulianDayNumber/IslamicCalendar.swift | 5 +---- Sources/JulianDayNumber/JulianCalendar.swift | 5 +---- .../JulianDayNumber/JulianDayNumberConverting.swift | 11 ++++++----- Sources/JulianDayNumber/KhwarizmianCalendar.swift | 5 +---- 8 files changed, 13 insertions(+), 33 deletions(-) diff --git a/Sources/JulianDayNumber/ArmenianCalendar.swift b/Sources/JulianDayNumber/ArmenianCalendar.swift index b077806..9c7e052 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar.swift @@ -83,14 +83,11 @@ extension ArmenianCalendar: JulianDayNumberConverting { /// A date in the Armenian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Armenian calendar. - static let julianDayNumberZero = (year: -5268, month: 11, day: 18) - /// Algorithm parameters for Armenian calendar conversions. static let conversionParameters = JDNConversionParameters(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { diff --git a/Sources/JulianDayNumber/CopticCalendar.swift b/Sources/JulianDayNumber/CopticCalendar.swift index 5e63104..d5399c9 100644 --- a/Sources/JulianDayNumber/CopticCalendar.swift +++ b/Sources/JulianDayNumber/CopticCalendar.swift @@ -100,14 +100,11 @@ extension CopticCalendar: JulianDayNumberConverting { /// A date in the Coptic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Coptic calendar. - static let julianDayNumberZero = (year: -4996, month: 5, day: 5) - /// Algorithm parameters for Coptic calendar conversions. static let conversionParameters = JDNConversionParameters(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { diff --git a/Sources/JulianDayNumber/EgyptianCalendar.swift b/Sources/JulianDayNumber/EgyptianCalendar.swift index 80018f1..58058fb 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar.swift @@ -84,14 +84,11 @@ extension EgyptianCalendar: JulianDayNumberConverting { /// A date in the Egyptian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Egyptian calendar. - static let julianDayNumberZero = (year: -3968, month: 2, day: 2) - /// Algorithm parameters for Egyptian calendar conversions. static let conversionParameters = JDNConversionParameters(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { diff --git a/Sources/JulianDayNumber/EthiopianCalendar.swift b/Sources/JulianDayNumber/EthiopianCalendar.swift index b5134c5..eafe7f6 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar.swift @@ -100,14 +100,11 @@ extension EthiopianCalendar: JulianDayNumberConverting { /// A date in the Ethiopian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Ethiopian calendar. - static let julianDayNumberZero = (year: -4720, month: 5, day: 5) - /// Algorithm parameters for Ethiopian calendar conversions. static let conversionParameters = JDNConversionParameters(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { diff --git a/Sources/JulianDayNumber/IslamicCalendar.swift b/Sources/JulianDayNumber/IslamicCalendar.swift index 109aeef..4aae375 100644 --- a/Sources/JulianDayNumber/IslamicCalendar.swift +++ b/Sources/JulianDayNumber/IslamicCalendar.swift @@ -102,14 +102,11 @@ extension IslamicCalendar: JulianDayNumberConverting { /// A date in the Islamic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Islamic calendar. - static let julianDayNumberZero = (year: -5498, month: 8, day: 16) - /// Algorithm parameters for Islamic calendar conversions. static let conversionParameters = JDNConversionParameters(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { diff --git a/Sources/JulianDayNumber/JulianCalendar.swift b/Sources/JulianDayNumber/JulianCalendar.swift index 5e24e87..3c02cfb 100644 --- a/Sources/JulianDayNumber/JulianCalendar.swift +++ b/Sources/JulianDayNumber/JulianCalendar.swift @@ -158,14 +158,11 @@ extension JulianCalendar: JulianDayNumberConverting { /// A date in the Julian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Julian calendar. - static let julianDayNumberZero = (year: -4712, month: 1, day: 1) - /// Algorithm parameters for Julian calendar conversions. static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { diff --git a/Sources/JulianDayNumber/JulianDayNumberConverting.swift b/Sources/JulianDayNumber/JulianDayNumberConverting.swift index c8549a7..0dd6aff 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverting.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverting.swift @@ -59,11 +59,13 @@ extension JulianDayNumberConverting where DateType == (year: Int, month: Int, da /// Algorithm parameters for converting a Julian day number to a year, month, and day. struct JDNConversionParameters { + /// The number of years in the computational calendar which precede the epoch. let y: Int + /// The number of days the epoch of the computational calendar (0/0/0) precedes day zero. let j: Int /// The month number which corresponds to month zero in the computational calendar. let m: Int - /// The number of months in a year (counting any epagonomai as an extra month). + /// The number of months in a year, counting any epagonomai as an extra month. let n: Int /// The number of years in an intercalation cycle. let r: Int @@ -96,15 +98,14 @@ typealias YearMonthDay = (year: Int, month: Int, day: Int) /// /// - parameter date: A date to convert. /// - parameter parameters: Parameters for the conversion algorithm. -/// - parameter jdnZero: The date for which the Julian day number is zero. /// /// - returns: The Julian day number corresponding to the specified date. -func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, jdnZero: YearMonthDay) -> JulianDayNumber { +func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 - if date < jdnZero { - ΔcalendarCycles = (jdnZero.year - Y - 1) / parameters.r + 1 + if Y <= -parameters.y { + ΔcalendarCycles = (-parameters.y - Y) / parameters.r + 1 Y += ΔcalendarCycles * parameters.r } diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar.swift b/Sources/JulianDayNumber/KhwarizmianCalendar.swift index 1ca3c82..e493be4 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar.swift @@ -83,14 +83,11 @@ extension KhwarizmianCalendar: JulianDayNumberConverting { /// A date in the Khwarizmian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The date for Julian day number zero in the proleptic Khwarizmian calendar. - static let julianDayNumberZero = (year: -5348, month: 11, day: 18) - /// Algorithm parameters for Khwarizmian calendar conversions. static let conversionParameters = JDNConversionParameters(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, jdnZero: julianDayNumberZero) + jdnFromDate(date, conversionParameters: conversionParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { From 11e3a786ffc27ee9f6c4d8a3c420f214d4dbb3f0 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 09:25:00 -0600 Subject: [PATCH 13/45] Use struct for algorithm constants --- Sources/JulianDayNumber/SakaCalendar.swift | 71 ++++++++-------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/Sources/JulianDayNumber/SakaCalendar.swift b/Sources/JulianDayNumber/SakaCalendar.swift index 2b7618c..0d39f1a 100644 --- a/Sources/JulianDayNumber/SakaCalendar.swift +++ b/Sources/JulianDayNumber/SakaCalendar.swift @@ -129,37 +129,31 @@ public struct SakaCalendar { } } -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. +// Algorithm adapted from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. extension SakaCalendar: JulianDayNumberConverting { /// A date in the Śaka calendar consists of a year, month, and day. public typealias DateType = (year: Int, month: Int, day: Int) - /// The intercalating cycle of the Śaka calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic Śaka calendar. - static let julianDayNumberZero = (year: -4791, month: 9, day: 3) - public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 - if date < julianDayNumberZero { - ΔcalendarCycles = (julianDayNumberZero.year - Y - 1) / intercalatingCycle.years + 1 - Y += ΔcalendarCycles * intercalatingCycle.years + if Y <= -conversionParameters.y { + ΔcalendarCycles = (-conversionParameters.y - Y) / gregorianIntercalatingCycle.years + 1 + Y += ΔcalendarCycles * gregorianIntercalatingCycle.years } - let h = date.month - m - let g = Y + y - (n - h) / n - let f = (h - 1 + n) % n - let e = (p * g + q) / r + date.day - 1 - j + let h = date.month - conversionParameters.m + let g = Y + conversionParameters.y - (conversionParameters.n - h) / conversionParameters.n + let f = (h - 1 + conversionParameters.n) % conversionParameters.n + let e = (conversionParameters.p * g + conversionParameters.q) / conversionParameters.r + date.day - 1 - conversionParameters.j let Z = f / 6 - var J = e + ((31 - Z) * f + 5 * Z) / u - J = J - (3 * ((g + A) / 100)) / 4 - C + var J = e + ((31 - Z) * f + 5 * Z) / conversionParameters.u + J = J - (3 * ((g + gregorianIntercalatingParameters.A) / 100)) / 4 - gregorianIntercalatingParameters.C if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * intercalatingCycle.days + J -= ΔcalendarCycles * gregorianIntercalatingCycle.days } return J @@ -171,45 +165,34 @@ extension SakaCalendar: JulianDayNumberConverting { // Richards' algorithm is only valid for positive JDNs. if J < 0 { - ΔcalendarCycles = -J / intercalatingCycle.days + 1 - J += ΔcalendarCycles * intercalatingCycle.days + ΔcalendarCycles = -J / gregorianIntercalatingCycle.days + 1 + J += ΔcalendarCycles * gregorianIntercalatingCycle.days } - var f = J + j - f = f + (((4 * J + B) / 146097) * 3) / 4 + C - let e = r * f + v - let g = (e % p) / r + var f = J + conversionParameters.j + f = f + (((4 * J + gregorianIntercalatingParameters.B) / 146097) * 3) / 4 + gregorianIntercalatingParameters.C + let e = conversionParameters.r * f + conversionParameters.v + let g = (e % conversionParameters.p) / conversionParameters.r let X = g / 365 let Z = g / 185 - X let s = 31 - Z let w = -5 * Z - let h = u * g + w - let D = (6 * X + (h % s)) / u + 1 + let h = conversionParameters.u * g + w + let D = (6 * X + (h % s)) / conversionParameters.u + 1 - let M = ((h / s + m) % n) + 1 - var Y = e / p - y + (n + m - M) / n + let M = ((h / s + conversionParameters.m) % conversionParameters.n) + 1 + var Y = e / conversionParameters.p - conversionParameters.y + (conversionParameters.n + conversionParameters.m - M) / conversionParameters.n if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * intercalatingCycle.years + Y -= ΔcalendarCycles * gregorianIntercalatingCycle.years } return (Y, M, D) } - // Constants for Śaka calendar conversions - static let y = 4794 - static let j = 1348 - static let m = 1 - static let n = 12 - static let r = 4 - static let p = 1461 - static let q = 0 - static let v = 3 - static let u = 1 - static let s = 31 - static let t = 0 - static let w = 0 - static let A = 184 - static let B = 274073 - static let C = -36 + /// Algorithm parameters for Śaka calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4794, j: 1348, m: 1, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 31, t: 0, w: 0) + + /// Gregorian intercalating parameters for Śaka calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274073, C: -36) } From 4168bb6e1b7f885a2baaf23dbbd6a01a6845dabc Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 09:25:30 -0600 Subject: [PATCH 14/45] Add intercalating cycle struct --- Sources/JulianDayNumber/HebrewCalendar.swift | 29 ++++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/Sources/JulianDayNumber/HebrewCalendar.swift b/Sources/JulianDayNumber/HebrewCalendar.swift index 8ace8eb..45d7042 100644 --- a/Sources/JulianDayNumber/HebrewCalendar.swift +++ b/Sources/JulianDayNumber/HebrewCalendar.swift @@ -193,8 +193,8 @@ public struct HebrewCalendar { var ΔcalendarCycles = 0 if Y < 1 { - ΔcalendarCycles = (1 - Y) / calendarCycleYears + 1 - Y += ΔcalendarCycles * calendarCycleYears + ΔcalendarCycles = (1 - Y) / intercalatingCycle.years + 1 + Y += ΔcalendarCycles * intercalatingCycle.years } let a = firstDayOfTishrei(year: Y) @@ -209,7 +209,7 @@ public struct HebrewCalendar { } } -// Algorithm from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. +// Algorithm adapted from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. extension HebrewCalendar { /// Returns the Julian day number of the first day of Tishrei in the specified year. @@ -262,23 +262,16 @@ extension HebrewCalendar: JulianDayNumberConverting { /// A date in the Hebrew calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The number of years in a cycle of the Hebrew calendar. - /// - /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. - static let calendarCycleYears = 689472 - - /// The number of days in a cycle of the Hebrew calendar. - /// - /// A cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. - static let calendarCycleDays = 251827457 + /// An intercalating cycle in the Hebrew calendar consists of 689,472 years, 8,527,680 months, 35,975,351 weeks, or 251,827,457 days. + static let intercalatingCycle = (years: 689472, days: 251827457) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 if Y < 1 { - ΔcalendarCycles = (1 - Y) / calendarCycleYears + 1 - Y += ΔcalendarCycles * calendarCycleYears + ΔcalendarCycles = (1 - Y) / intercalatingCycle.years + 1 + Y += ΔcalendarCycles * intercalatingCycle.years } let a = firstDayOfTishrei(year: Y) @@ -287,7 +280,7 @@ extension HebrewCalendar: JulianDayNumberConverting { var J = a + A[K - 1][date.month - 1] + date.day - 1 if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * calendarCycleDays + J -= ΔcalendarCycles * intercalatingCycle.days } return J @@ -298,8 +291,8 @@ extension HebrewCalendar: JulianDayNumberConverting { var ΔcalendarCycles = 0 if J < epochJulianDayNumber { - ΔcalendarCycles = (epochJulianDayNumber - J) / calendarCycleDays + 1 - J += ΔcalendarCycles * calendarCycleDays + ΔcalendarCycles = (epochJulianDayNumber - J) / intercalatingCycle.days + 1 + J += ΔcalendarCycles * intercalatingCycle.days } var Y = yearContaining(julianDayNumber: J) @@ -313,7 +306,7 @@ extension HebrewCalendar: JulianDayNumberConverting { let D = c - AK[M - 1] if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * calendarCycleYears + Y -= ΔcalendarCycles * intercalatingCycle.years } return (Y, M, D) From d459ddb9982a28de2664f0a76f4dc9f2d6b56b61 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 09:26:17 -0600 Subject: [PATCH 15/45] Refactor Gregorian-type intercalating --- Sources/JulianDayNumber/BahaiCalendar.swift | 10 ++----- .../FrenchRepublicanCalendar.swift | 10 ++----- .../JulianDayNumber/GregorianCalendar.swift | 10 ++----- .../JulianDayNumberConverting.swift | 28 ++++++++++--------- 4 files changed, 21 insertions(+), 37 deletions(-) diff --git a/Sources/JulianDayNumber/BahaiCalendar.swift b/Sources/JulianDayNumber/BahaiCalendar.swift index e884a53..e198aab 100644 --- a/Sources/JulianDayNumber/BahaiCalendar.swift +++ b/Sources/JulianDayNumber/BahaiCalendar.swift @@ -139,12 +139,6 @@ extension BahaiCalendar: JulianDayNumberConverting { /// A date in the Baháʼí calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the Baháʼí calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic Baháʼí calendar. - static let julianDayNumberZero = (year: -6556, month: 14, day: 2) - /// Algorithm parameters for Baháʼí calendar conversions. static let conversionParameters = JDNConversionParameters(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0) @@ -152,10 +146,10 @@ extension BahaiCalendar: JulianDayNumberConverting { static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274273, C: -50) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) } } diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift index 4cade50..a9a2470 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift @@ -137,12 +137,6 @@ extension FrenchRepublicanCalendar: JulianDayNumberConverting { /// A date in the French Republican calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// The intercalating cycle of the French Republican calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic French Republican calendar. - static let julianDayNumberZero = (year: -6504, month: 3, day: 3) - /// Algorithm parameters for French Republican calendar conversions. static let conversionParameters = JDNConversionParameters(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) @@ -150,10 +144,10 @@ extension FrenchRepublicanCalendar: JulianDayNumberConverting { static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 396, B: 578797, C: -51) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) } } diff --git a/Sources/JulianDayNumber/GregorianCalendar.swift b/Sources/JulianDayNumber/GregorianCalendar.swift index 0596c52..ebcba6b 100644 --- a/Sources/JulianDayNumber/GregorianCalendar.swift +++ b/Sources/JulianDayNumber/GregorianCalendar.swift @@ -178,12 +178,6 @@ extension GregorianCalendar: JulianDayNumberConverting { /// A date in the Gregorian calendar consists of a year, month, and day. public typealias DateType = JulianCalendar.DateType - /// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. - static let intercalatingCycle = (years: 400, days: 146097) - - /// The date for Julian day number zero in the proleptic Gregorian calendar. - static let julianDayNumberZero = (year: -4713, month: 11, day: 24) - /// Algorithm parameters for Gregorian calendar conversions. static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) @@ -191,10 +185,10 @@ extension GregorianCalendar: JulianDayNumberConverting { static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274277, C: -38) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, jdnZero: julianDayNumberZero, intercalatingCycle: intercalatingCycle) + jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters, intercalatingCycle: intercalatingCycle) + dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) } } diff --git a/Sources/JulianDayNumber/JulianDayNumberConverting.swift b/Sources/JulianDayNumber/JulianDayNumberConverting.swift index 0dd6aff..786f882 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverting.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverting.swift @@ -55,7 +55,7 @@ extension JulianDayNumberConverting where DateType == (year: Int, month: Int, da // MARK: - Conversion Algorithms -// Algorithms from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. +// Algorithms adapted from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. /// Algorithm parameters for converting a Julian day number to a year, month, and day. struct JDNConversionParameters { @@ -157,6 +157,11 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve return (Y, M, D) } +// TODO: Figure out a way to use the Gregorian intercalating parameters A, B and C instead + +/// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. +let gregorianIntercalatingCycle = (years: 400, days: 146097) + /// Converts a date to a Julian day number using the specified conversion parameters and returns the result. /// /// - important: No validation checks are performed on the date values. @@ -164,17 +169,15 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve /// - parameter date: A date to convert. /// - parameter parameters: Parameters for the conversion algorithm. /// - parameter gregorianIntercalatingParameters: Parameters for Gregorian-type intercalating. -/// - parameter jdnZero: The date for which the Julian day number is zero. -/// - parameter intercalatingCycle: The calendar's intercalating cycle. /// /// - returns: The Julian day number corresponding to the specified date. -func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters, jdnZero: YearMonthDay, intercalatingCycle: IntercalatingCycle) -> JulianDayNumber { +func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 - if date < jdnZero { - ΔcalendarCycles = (jdnZero.year - Y - 1) / intercalatingCycle.years + 1 - Y += ΔcalendarCycles * intercalatingCycle.years + if Y <= -parameters.y { + ΔcalendarCycles = (-parameters.y - Y) / gregorianIntercalatingCycle.years + 1 + Y += ΔcalendarCycles * gregorianIntercalatingCycle.years } let h = date.month - parameters.m @@ -185,7 +188,7 @@ func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConve J = J - (3 * ((g + gregorianIntercalatingParameters.A) / 100)) / 4 - gregorianIntercalatingParameters.C if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * intercalatingCycle.days + J -= ΔcalendarCycles * gregorianIntercalatingCycle.days } return J @@ -196,17 +199,16 @@ func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConve /// - parameter J: A Julian day number. /// - parameter parameters: Parameters for the conversion algorithm. /// - parameter gregorianIntercalatingParameters: Parameters for Gregorian-type intercalating. -/// - parameter intercalatingCycle: The calendar's intercalating cycle. /// /// - returns: The date corresponding to the specified Julian day number. -func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters, intercalatingCycle: IntercalatingCycle) -> YearMonthDay { +func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters) -> YearMonthDay { var J = J var ΔcalendarCycles = 0 // Richards' algorithm is only valid for positive JDNs. if J < 0 { - ΔcalendarCycles = -J / intercalatingCycle.days + 1 - J += ΔcalendarCycles * intercalatingCycle.days + ΔcalendarCycles = -J / gregorianIntercalatingCycle.days + 1 + J += ΔcalendarCycles * gregorianIntercalatingCycle.days } precondition(J <= Int.max - parameters.j, "Julian day number too large") @@ -221,7 +223,7 @@ func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConve var Y = e / parameters.p - parameters.y + (parameters.n + parameters.m - M) / parameters.n if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * intercalatingCycle.years + Y -= ΔcalendarCycles * gregorianIntercalatingCycle.years } return (Y, M, D) From 4484bc0cbcaffe4698d436b7630cafa5ba65f3a8 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 09:33:31 -0600 Subject: [PATCH 16/45] Add precondition --- Sources/JulianDayNumber/SakaCalendar.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/JulianDayNumber/SakaCalendar.swift b/Sources/JulianDayNumber/SakaCalendar.swift index 0d39f1a..dac04b2 100644 --- a/Sources/JulianDayNumber/SakaCalendar.swift +++ b/Sources/JulianDayNumber/SakaCalendar.swift @@ -169,6 +169,8 @@ extension SakaCalendar: JulianDayNumberConverting { J += ΔcalendarCycles * gregorianIntercalatingCycle.days } + precondition(J <= Int.max - conversionParameters.j, "Julian day number too large") + var f = J + conversionParameters.j f = f + (((4 * J + gregorianIntercalatingParameters.B) / 146097) * 3) / 4 + gregorianIntercalatingParameters.C let e = conversionParameters.r * f + conversionParameters.v From 56896c45a8f78dccb7268c7e4b3f4117127296f0 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 09:54:57 -0600 Subject: [PATCH 17/45] New arithmetic limits --- .../ArmenianCalendarTests.swift | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/Tests/JulianDayNumberTests/ArmenianCalendarTests.swift b/Tests/JulianDayNumberTests/ArmenianCalendarTests.swift index 33c21db..4c142e3 100644 --- a/Tests/JulianDayNumberTests/ArmenianCalendarTests.swift +++ b/Tests/JulianDayNumberTests/ArmenianCalendarTests.swift @@ -48,31 +48,18 @@ final class ArmenianCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForArmenianCalendar = -9223372036854775514 - (Y, M, D) = ArmenianCalendar.dateFromJulianDayNumber(smallestJDNForArmenianCalendar) +// let smallestJDNForArmenianCalendar = Int.min + 294 + // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom + let smallestJDNForArmenianCalendar = Int.min + 341 + var (Y, M, D) = ArmenianCalendar.dateFromJulianDayNumber(smallestJDNForArmenianCalendar) var jdn = ArmenianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForArmenianCalendar, jdn) // Values larger than this cause an arithmetic overflow in dateFromJulianDayNumber - let largestJDNForArmenianCalendar = 9223372036854775490 + let largestJDNForArmenianCalendar = Int.max - 317 (Y, M, D) = ArmenianCalendar.dateFromJulianDayNumber(largestJDNForArmenianCalendar) jdn = ArmenianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForArmenianCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForArmenianCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = ArmenianCalendar.dateAndTimeFromJulianDate(smallestJDForArmenianCalendar) - var jd = ArmenianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForArmenianCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForArmenianCalendar = 0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = ArmenianCalendar.dateAndTimeFromJulianDate(largestJDForArmenianCalendar) - jd = ArmenianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForArmenianCalendar, jd) } } From e69dffa1f12b60e80b0564ae7ce2e13063d5337a Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 10:10:08 -0600 Subject: [PATCH 18/45] Adjust arithmetic limits --- .../KhwarizmianCalendarTests.swift | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/Tests/JulianDayNumberTests/KhwarizmianCalendarTests.swift b/Tests/JulianDayNumberTests/KhwarizmianCalendarTests.swift index a6f9da1..19ad7dc 100644 --- a/Tests/JulianDayNumberTests/KhwarizmianCalendarTests.swift +++ b/Tests/JulianDayNumberTests/KhwarizmianCalendarTests.swift @@ -46,31 +46,18 @@ final class KhwarizmianCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForKhwarizmianCalendar = -9223372036854775514 - (Y, M, D) = KhwarizmianCalendar.dateFromJulianDayNumber(smallestJDNForKhwarizmianCalendar) +// let smallestJDNForKhwarizmianCalendar = Int.min + 294 + // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom + let smallestJDNForKhwarizmianCalendar = Int.min + 341 + var (Y, M, D) = KhwarizmianCalendar.dateFromJulianDayNumber(smallestJDNForKhwarizmianCalendar) var jdn = KhwarizmianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForKhwarizmianCalendar, jdn) // Values larger than this cause an arithmetic overflow in dateFromJulianDayNumber - let largestJDNForKhwarizmianCalendar = 9223372036854775490 + let largestJDNForKhwarizmianCalendar = Int.max - 317 (Y, M, D) = KhwarizmianCalendar.dateFromJulianDayNumber(largestJDNForKhwarizmianCalendar) jdn = KhwarizmianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForKhwarizmianCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForKhwarizmianCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = KhwarizmianCalendar.dateAndTimeFromJulianDate(smallestJDForKhwarizmianCalendar) - var jd = KhwarizmianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForKhwarizmianCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForKhwarizmianCalendar = 0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = KhwarizmianCalendar.dateAndTimeFromJulianDate(largestJDForKhwarizmianCalendar) - jd = KhwarizmianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForKhwarizmianCalendar, jd) } } From d1f4093d12b1fe5da7c630993d797d7375dac9a8 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 10:13:52 -0600 Subject: [PATCH 19/45] Adjust arithmetic limits --- .../BahaiCalendarTests.swift | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/BahaiCalendarTests.swift b/Tests/JulianDayNumberTests/BahaiCalendarTests.swift index 60cebc4..a80c5d1 100644 --- a/Tests/JulianDayNumberTests/BahaiCalendarTests.swift +++ b/Tests/JulianDayNumberTests/BahaiCalendarTests.swift @@ -86,12 +86,9 @@ final class BahaiCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForBahaiCalendar = -9223372036854719351 - (Y, M, D) = BahaiCalendar.dateFromJulianDayNumber(smallestJDNForBahaiCalendar) + let smallestJDNForBahaiCalendar = Int.min + 56457 + var (Y, M, D) = BahaiCalendar.dateFromJulianDayNumber(smallestJDNForBahaiCalendar) var jdn = BahaiCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForBahaiCalendar, jdn) @@ -100,17 +97,5 @@ final class BahaiCalendarTests: XCTestCase { (Y, M, D) = BahaiCalendar.dateFromJulianDayNumber(largestJDNForBahaiCalendar) jdn = BahaiCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForBahaiCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForBahaiCalendar = -0x1.fffffffffffc8p+62 - (Y, M, D, h, m, s) = BahaiCalendar.dateAndTimeFromJulianDate(smallestJDForBahaiCalendar) - var jd = BahaiCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForBahaiCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForBahaiCalendar = 0x1.fffd4eff4e5d7p+60 - (Y, M, D, h, m, s) = BahaiCalendar.dateAndTimeFromJulianDate(largestJDForBahaiCalendar) - jd = BahaiCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForBahaiCalendar, jd) } } From 83f9187ecd61e57d67a54ab0ff3f7af510efd62b Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 10:21:12 -0600 Subject: [PATCH 20/45] Adjust arithmetic limits --- .../EgyptianCalendarTests.swift | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/Tests/JulianDayNumberTests/EgyptianCalendarTests.swift b/Tests/JulianDayNumberTests/EgyptianCalendarTests.swift index 5ad1179..2a9ebf2 100644 --- a/Tests/JulianDayNumberTests/EgyptianCalendarTests.swift +++ b/Tests/JulianDayNumberTests/EgyptianCalendarTests.swift @@ -54,31 +54,18 @@ final class EgyptianCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForEgyptianCalendar = -9223372036854775514 - (Y, M, D) = EgyptianCalendar.dateFromJulianDayNumber(smallestJDNForEgyptianCalendar) +// let smallestJDNForEgyptianCalendar = Int.min + 293 + // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom + let smallestJDNForEgyptianCalendar = Int.min + 611 + var (Y, M, D) = EgyptianCalendar.dateFromJulianDayNumber(smallestJDNForEgyptianCalendar) var jdn = EgyptianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForEgyptianCalendar, jdn) // Values larger than this cause an arithmetic overflow in dateFromJulianDayNumber - let largestJDNForEgyptianCalendar = 9223372036854775760 + let largestJDNForEgyptianCalendar = Int.max - 47 (Y, M, D) = EgyptianCalendar.dateFromJulianDayNumber(largestJDNForEgyptianCalendar) jdn = EgyptianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForEgyptianCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForEgyptianCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = EgyptianCalendar.dateAndTimeFromJulianDate(smallestJDForEgyptianCalendar) - var jd = EgyptianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForEgyptianCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForEgyptianCalendar = 0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = EgyptianCalendar.dateAndTimeFromJulianDate(largestJDForEgyptianCalendar) - jd = EgyptianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForEgyptianCalendar, jd) } } From ff4388a4a8e1a63ffe01dad1eb0b2d2fab505c4c Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 11:44:16 -0600 Subject: [PATCH 21/45] Adjust arithmetic limits --- .../CopticCalendarTests.swift | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/CopticCalendarTests.swift b/Tests/JulianDayNumberTests/CopticCalendarTests.swift index b136c53..22cd21d 100644 --- a/Tests/JulianDayNumberTests/CopticCalendarTests.swift +++ b/Tests/JulianDayNumberTests/CopticCalendarTests.swift @@ -74,12 +74,11 @@ final class CopticCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForCopticCalendar = -9223372036854775664 - (Y, M, D) = CopticCalendar.dateFromJulianDayNumber(smallestJDNForCopticCalendar) +// let smallestJDNForCopticCalendar = Int.min + 144 + // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom + let smallestJDNForCopticCalendar = Int.min + 384 + var (Y, M, D) = CopticCalendar.dateFromJulianDayNumber(smallestJDNForCopticCalendar) var jdn = CopticCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForCopticCalendar, jdn) @@ -88,17 +87,5 @@ final class CopticCalendarTests: XCTestCase { (Y, M, D) = CopticCalendar.dateFromJulianDayNumber(largestJDNForCopticCalendar) jdn = CopticCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForCopticCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForCopticCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = CopticCalendar.dateAndTimeFromJulianDate(smallestJDForCopticCalendar) - var jd = CopticCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForCopticCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForCopticCalendar = 0x1.fffffffffffffp+60 - (Y, M, D, h, m, s) = CopticCalendar.dateAndTimeFromJulianDate(largestJDForCopticCalendar) - jd = CopticCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForCopticCalendar, jd) } } From 5fcd6ee1b482e01ebc19bc06f61009ab9cb31a48 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 11:51:59 -0600 Subject: [PATCH 22/45] Adjust arithmetic limits --- .../EthiopianCalendarTests.swift | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/EthiopianCalendarTests.swift b/Tests/JulianDayNumberTests/EthiopianCalendarTests.swift index 4ec9d85..5bf154a 100644 --- a/Tests/JulianDayNumberTests/EthiopianCalendarTests.swift +++ b/Tests/JulianDayNumberTests/EthiopianCalendarTests.swift @@ -77,12 +77,11 @@ final class EthiopianCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForEthiopianCalendar = -9223372036854775664 - (Y, M, D) = EthiopianCalendar.dateFromJulianDayNumber(smallestJDNForEthiopianCalendar) +// let smallestJDNForEthiopianCalendar = Int.min + 144 + // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom + let smallestJDNForEthiopianCalendar = Int.min + 384 + var (Y, M, D) = EthiopianCalendar.dateFromJulianDayNumber(smallestJDNForEthiopianCalendar) var jdn = EthiopianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForEthiopianCalendar, jdn) @@ -91,17 +90,5 @@ final class EthiopianCalendarTests: XCTestCase { (Y, M, D) = EthiopianCalendar.dateFromJulianDayNumber(largestJDNForEthiopianCalendar) jdn = EthiopianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForEthiopianCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForEthiopianCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = EthiopianCalendar.dateAndTimeFromJulianDate(smallestJDForEthiopianCalendar) - var jd = EthiopianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForEthiopianCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForEthiopianCalendar = 0x1.fffffffffffffp+60 - (Y, M, D, h, m, s) = EthiopianCalendar.dateAndTimeFromJulianDate(largestJDForEthiopianCalendar) - jd = EthiopianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForEthiopianCalendar, jd) } } From 1d8bb3896a9e0538db1ac45dab6abefe387ddd5b Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 11:56:16 -0600 Subject: [PATCH 23/45] Adjust arithmetic limits --- .../IslamicCalendarTests.swift | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/IslamicCalendarTests.swift b/Tests/JulianDayNumberTests/IslamicCalendarTests.swift index 51b20fe..a284e23 100644 --- a/Tests/JulianDayNumberTests/IslamicCalendarTests.swift +++ b/Tests/JulianDayNumberTests/IslamicCalendarTests.swift @@ -101,12 +101,9 @@ final class IslamicCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForIslamicCalendar = -9223372036854775352 - (Y, M, D) = IslamicCalendar.dateFromJulianDayNumber(smallestJDNForIslamicCalendar) + let smallestJDNForIslamicCalendar = Int.min + 325 + var (Y, M, D) = IslamicCalendar.dateFromJulianDayNumber(smallestJDNForIslamicCalendar) var jdn = IslamicCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForIslamicCalendar, jdn) @@ -115,17 +112,5 @@ final class IslamicCalendarTests: XCTestCase { (Y, M, D) = IslamicCalendar.dateFromJulianDayNumber(largestJDNForIslamicCalendar) jdn = IslamicCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForIslamicCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForIslamicCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = IslamicCalendar.dateAndTimeFromJulianDate(smallestJDForIslamicCalendar) - var jd = IslamicCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForIslamicCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForIslamicCalendar = 0x1.1111111111099p+58 - (Y, M, D, h, m, s) = IslamicCalendar.dateAndTimeFromJulianDate(largestJDForIslamicCalendar) - jd = IslamicCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForIslamicCalendar, jd) } } From 18eecc84bc8eafecb1e508ebe8d4f50f86d06616 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 11:58:25 -0600 Subject: [PATCH 24/45] Adjust arithmetic limits --- Tests/JulianDayNumberTests/MayaCalendarTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/JulianDayNumberTests/MayaCalendarTests.swift b/Tests/JulianDayNumberTests/MayaCalendarTests.swift index 2b2737d..673860f 100644 --- a/Tests/JulianDayNumberTests/MayaCalendarTests.swift +++ b/Tests/JulianDayNumberTests/MayaCalendarTests.swift @@ -68,9 +68,9 @@ final class MayaCalendarTests: XCTestCase { var b, k, t, u, d: Int // Values smaller than this cause an arithmetic overflow in longCountFromJulianDayNumber -// let smallestJDNForMayaCalendar = -9223372036854191525 +// let smallestJDNForMayaCalendar = Int.min + 584283 // Values smaller than this cause an arithmetic overflow in julianDayNumberFromLongCount - let smallestJDNForMayaCalendar = -9223372036854191517 + let smallestJDNForMayaCalendar = Int.min + 584291 (b, k, t, u, d) = MayaCalendar.longCountFromJulianDayNumber(smallestJDNForMayaCalendar) var jdn = MayaCalendar.julianDayNumberFromLongCount(baktun: b, katun: k, tun: t, uinal: u, kin: d) XCTAssertEqual(smallestJDNForMayaCalendar, jdn) From b794da464d74f9eb80608dbb358bb13d19097e8e Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 12:01:30 -0600 Subject: [PATCH 25/45] Adjust arithmetic limits --- .../JulianCalendarTests.swift | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/JulianCalendarTests.swift b/Tests/JulianDayNumberTests/JulianCalendarTests.swift index 45059c5..2523ab2 100644 --- a/Tests/JulianDayNumberTests/JulianCalendarTests.swift +++ b/Tests/JulianDayNumberTests/JulianCalendarTests.swift @@ -98,12 +98,9 @@ final class JulianCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForJulianCalendar = -9223372036854775664 - (Y, M, D) = JulianCalendar.dateFromJulianDayNumber(smallestJDNForJulianCalendar) + let smallestJDNForJulianCalendar = Int.min + 144 + var (Y, M, D) = JulianCalendar.dateFromJulianDayNumber(smallestJDNForJulianCalendar) var jdn = JulianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForJulianCalendar, jdn) @@ -112,17 +109,5 @@ final class JulianCalendarTests: XCTestCase { (Y, M, D) = JulianCalendar.dateFromJulianDayNumber(largestJDNForJulianCalendar) jdn = JulianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForJulianCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForJulianCalendar = -0x1.fffffffffffffp+62 - (Y, M, D, h, m, s) = JulianCalendar.dateAndTimeFromJulianDate(smallestJDForJulianCalendar) - var jd = JulianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForJulianCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForJulianCalendar = 0x1.ffffffffffffap+60 - (Y, M, D, h, m, s) = JulianCalendar.dateAndTimeFromJulianDate(largestJDForJulianCalendar) - jd = JulianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForJulianCalendar, jd) } } From 5d12be3fc4c198b52cfadf796a67da395827b5f2 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 12:10:40 -0600 Subject: [PATCH 26/45] Adjust arithmetic limit --- .../HebrewCalendarTests.swift | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/Tests/JulianDayNumberTests/HebrewCalendarTests.swift b/Tests/JulianDayNumberTests/HebrewCalendarTests.swift index 7678a05..1ff5162 100644 --- a/Tests/JulianDayNumberTests/HebrewCalendarTests.swift +++ b/Tests/JulianDayNumberTests/HebrewCalendarTests.swift @@ -218,15 +218,11 @@ final class HebrewCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber -// let smallestJDNForHebrewCalendar = -9223372036747815981 - // JDN -9223372036747815627 equals date (-25252436095246078-01-01) which is the smallest round-trippable value +// let smallestJDNForHebrewCalendar = Int.min + 106959827 // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom - let smallestJDNForHebrewCalendar = -9223372036747815627 - (Y, M, D) = HebrewCalendar.dateFromJulianDayNumber(smallestJDNForHebrewCalendar) + let smallestJDNForHebrewCalendar = Int.min + 106960181 + var (Y, M, D) = HebrewCalendar.dateFromJulianDayNumber(smallestJDNForHebrewCalendar) var jdn = HebrewCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForHebrewCalendar, jdn) @@ -236,20 +232,5 @@ final class HebrewCalendarTests: XCTestCase { (Y, M, D) = HebrewCalendar.dateFromJulianDayNumber(largestJDNForHebrewCalendar) jdn = HebrewCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForHebrewCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate -// let smallestJDForHebrewCalendar = -0x1.ffffffffe67fbp+62 - // JD -0x1.ffffffffe67fap+62 equals date (-25252436095246077-13-07 00:00:00) which is the smallest round-trippable value - // Values smaller than this cause an arithmetic overflow in julianDateFrom - let smallestJDForHebrewCalendar = -0x1.ffffffffe67fap+62 - (Y, M, D, h, m, s) = HebrewCalendar.dateAndTimeFromJulianDate(smallestJDForHebrewCalendar) - var jd = HebrewCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForHebrewCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForHebrewCalendar = 0x1.43a273100de27p+48 - (Y, M, D, h, m, s) = HebrewCalendar.dateAndTimeFromJulianDate(largestJDForHebrewCalendar) - jd = HebrewCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForHebrewCalendar, jd) } } From 14ca6e1002bd5127e8dd67ef5458136bc1f6ec46 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 13:35:47 -0600 Subject: [PATCH 27/45] Adjust arithmetic limits --- .../GregorianCalendarTests.swift | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/GregorianCalendarTests.swift b/Tests/JulianDayNumberTests/GregorianCalendarTests.swift index 58a63a1..e7c8fbb 100644 --- a/Tests/JulianDayNumberTests/GregorianCalendarTests.swift +++ b/Tests/JulianDayNumberTests/GregorianCalendarTests.swift @@ -105,12 +105,9 @@ final class GregorianCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForGregorianCalendar = -9223372036854719351 - (Y, M, D) = GregorianCalendar.dateFromJulianDayNumber(smallestJDNForGregorianCalendar) + let smallestJDNForGregorianCalendar = Int.min + 56457 + var (Y, M, D) = GregorianCalendar.dateFromJulianDayNumber(smallestJDNForGregorianCalendar) var jdn = GregorianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForGregorianCalendar, jdn) @@ -119,17 +116,5 @@ final class GregorianCalendarTests: XCTestCase { (Y, M, D) = GregorianCalendar.dateFromJulianDayNumber(largestJDNForGregorianCalendar) jdn = GregorianCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForGregorianCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForGregorianCalendar = -0x1.fffffffffffc8p+62 - (Y, M, D, h, m, s) = GregorianCalendar.dateAndTimeFromJulianDate(smallestJDForGregorianCalendar) - var jd = GregorianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForGregorianCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForGregorianCalendar = 0x1.fffd4eff4e5d7p+60 - (Y, M, D, h, m, s) = GregorianCalendar.dateAndTimeFromJulianDate(largestJDForGregorianCalendar) - jd = GregorianCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForGregorianCalendar, jd) } } From b5502bd33e6b4f556bb2bb738fa17004d906d0fe Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 13:46:08 -0600 Subject: [PATCH 28/45] Update arithmetic limits --- .../FrenchRepublicanCalendarTests.swift | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/FrenchRepublicanCalendarTests.swift b/Tests/JulianDayNumberTests/FrenchRepublicanCalendarTests.swift index 6765f1a..2dc2d54 100644 --- a/Tests/JulianDayNumberTests/FrenchRepublicanCalendarTests.swift +++ b/Tests/JulianDayNumberTests/FrenchRepublicanCalendarTests.swift @@ -69,12 +69,11 @@ final class FrenchRepublicanCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForFrenchRepublicanCalendar = -9223372036854719351 - (Y, M, D) = FrenchRepublicanCalendar.dateFromJulianDayNumber(smallestJDNForFrenchRepublicanCalendar) +// let smallestJDNForFrenchRepublicanCalendar = Int.min + 56456 + // Values smaller than this cause an arithmetic overflow in julianDayNumberFrom + let smallestJDNForFrenchRepublicanCalendar = Int.min + 56759 + var (Y, M, D) = FrenchRepublicanCalendar.dateFromJulianDayNumber(smallestJDNForFrenchRepublicanCalendar) var jdn = FrenchRepublicanCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForFrenchRepublicanCalendar, jdn) @@ -83,17 +82,5 @@ final class FrenchRepublicanCalendarTests: XCTestCase { (Y, M, D) = FrenchRepublicanCalendar.dateFromJulianDayNumber(largestJDNForFrenchRepublicanCalendar) jdn = FrenchRepublicanCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForFrenchRepublicanCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForFrenchRepublicanCalendar = -0x1.fffffffffffc8p+62 - (Y, M, D, h, m, s) = FrenchRepublicanCalendar.dateAndTimeFromJulianDate(smallestJDForFrenchRepublicanCalendar) - var jd = FrenchRepublicanCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForFrenchRepublicanCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForFrenchRepublicanCalendar = 0x1.fffd4eff4e5dcp+60 - (Y, M, D, h, m, s) = FrenchRepublicanCalendar.dateAndTimeFromJulianDate(largestJDForFrenchRepublicanCalendar) - jd = FrenchRepublicanCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForFrenchRepublicanCalendar, jd) } } From a19ab687c10efb3440ce3504394e626d95e6d56c Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 13:48:11 -0600 Subject: [PATCH 29/45] Update arithmetic limits --- .../SakaCalendarTests.swift | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Tests/JulianDayNumberTests/SakaCalendarTests.swift b/Tests/JulianDayNumberTests/SakaCalendarTests.swift index 6b355b8..ce9e7b5 100644 --- a/Tests/JulianDayNumberTests/SakaCalendarTests.swift +++ b/Tests/JulianDayNumberTests/SakaCalendarTests.swift @@ -72,12 +72,9 @@ final class SakaCalendarTests: XCTestCase { } func testArithmeticLimits() { - var Y, M, D, h, m: Int - var s: Double - // Values smaller than this cause an arithmetic overflow in dateFromJulianDayNumber - let smallestJDNForSakaCalendar = -9223372036854719351 - (Y, M, D) = SakaCalendar.dateFromJulianDayNumber(smallestJDNForSakaCalendar) + let smallestJDNForSakaCalendar = Int.min + 56457 + var (Y, M, D) = SakaCalendar.dateFromJulianDayNumber(smallestJDNForSakaCalendar) var jdn = SakaCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(smallestJDNForSakaCalendar, jdn) @@ -86,17 +83,5 @@ final class SakaCalendarTests: XCTestCase { (Y, M, D) = SakaCalendar.dateFromJulianDayNumber(largestJDNForSakaCalendar) jdn = SakaCalendar.julianDayNumberFrom(year: Y, month: M, day: D) XCTAssertEqual(largestJDNForSakaCalendar, jdn) - - // Values smaller than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let smallestJDForSakaCalendar = -0x1.fffffffffffc8p+62 - (Y, M, D, h, m, s) = SakaCalendar.dateAndTimeFromJulianDate(smallestJDForSakaCalendar) - var jd = SakaCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(smallestJDForSakaCalendar, jd) - - // Values larger than this cause an arithmetic overflow in dateAndTimeFromJulianDate - let largestJDForSakaCalendar = 0x1.fffd4eff4e5d8p+60 - (Y, M, D, h, m, s) = SakaCalendar.dateAndTimeFromJulianDate(largestJDForSakaCalendar) - jd = SakaCalendar.julianDateFrom(year: Y, month: M, day: D, hour: h, minute: m, second: s) - XCTAssertEqual(largestJDForSakaCalendar, jd) } } From fc5bcf2e222f2d43f259236812db8713b132d8af Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 13:48:21 -0600 Subject: [PATCH 30/45] Update limits --- README.md | 54 ++++++++++++++---------------------------------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index f64fec4..8e3e4cd 100644 --- a/README.md +++ b/README.md @@ -67,49 +67,23 @@ The [latest documentation](https://swiftpackageindex.com/sbooth/JulianDayNumber/ ## Limits -### Julian Day Numbers - -The following table summarizes the limits for Julian day numbers. Julian day numbers outside these values will cause an arithmetic overflow. +The following table summarizes the arithmetic limits for Julian day number calculations. | Calendar | Minimum JDN | Maximum JDN | | --- | --- | --- | -| Armenian | -9223372036854775514 | 9223372036854775490 | -| Baháʼí | -9223372036854719351 | 2305795661307959248 | -| Coptic | -9223372036854775664 | 2305843009213693827 | -| Egyptian | -9223372036854775514 | 9223372036854775760 | -| Ethiopian | -9223372036854775664 | 2305843009213693827 | -| French Republican | -9223372036854719351 | 2305795661307960548 | -| Gregorian | -9223372036854719351 | 2305795661307959247 | -| Hebrew | -9223372036747815981 ¹ | 355839970905570 | -| Islamic | -9223372036854775352 | 307445734561818195 | -| Julian | -9223372036854775664 | 2305843009213692550 | -| Khwarizmian | -9223372036854775514 | 9223372036854775490 | -| Maya Long Count | -9223372036854191525 ² | Int.max | -| Śaka | -9223372036854719351 | 2305795661307959298 | - -¹ The smallest round-trippable JDN for the Hebrew calendar is -9223372036747815627. -² The smallest round-trippable JDN for the Maya Long Count is -9223372036854191517. - -### Julian Dates - -The following table summarizes the limits for Julian dates. Julian dates outside these values will cause an arithmetic overflow. - -| Calendar | Minimum JD | Maximum JD | -| --- | --- | --- | -| Armenian | -0x1.fffffffffffffp+62 | 0x1.fffffffffffffp+62 | -| Baháʼí | -0x1.fffffffffffc8p+62 | 0x1.fffd4eff4e5d7p+60 | -| Coptic | -0x1.fffffffffffffp+62 | 0x1.fffffffffffffp+60 | -| Egyptian | -0x1.fffffffffffffp+62 | 0x1.fffffffffffffp+62 | -| Ethiopian | -0x1.fffffffffffffp+62 | 0x1.fffffffffffffp+60 | -| French Republican | -0x1.fffffffffffc8p+62 | 0x1.fffd4eff4e5dcp+60 | -| Gregorian | -0x1.fffffffffffc8p+62 | 0x1.fffd4eff4e5d7p+60 | -| Hebrew | -0x1.ffffffffe67fbp+62 ¹ | 0x1.43a273100de27p+48 | -| Islamic | -0x1.fffffffffffffp+62 | 0x1.1111111111099p+58 | -| Julian | -0x1.fffffffffffffp+62 | 0x1.ffffffffffffap+60 | -| Khwarizmian | -0x1.fffffffffffffp+62 | 0x1.fffffffffffffp+62 | -| Śaka | -0x1.fffffffffffc8p+62 | 0x1.fffd4eff4e5d8p+60 | - -¹ The smallest round-trippable JD for the Hebrew calendar is -0x1.ffffffffe67fap+62. +| Armenian | Int.min + 341 | Int.max - 317 | +| Baháʼí | Int.min + 56457 | 2305795661307959248 | +| Coptic | Int.min + 384 | 2305843009213693827 | +| Egyptian | Int.min + 611 | Int.max - 47 | +| Ethiopian | Int.min + 384 | 2305843009213693827 | +| French Republican | Int.min + 56759 | 2305795661307960548 | +| Gregorian | Int.min + 56457 | 2305795661307959247 | +| Hebrew | Int.min + 106960181 | 355839970905570 | +| Islamic | Int.min + 325 | 307445734561818195 | +| Julian | Int.min + 144 | 2305843009213692550 | +| Khwarizmian | Int.min + 341 | Int.max - 317 | +| Maya Long Count | Int.min + 584291 | Int.max | +| Śaka | Int.min + 56457 | 2305795661307959298 | ## License From 1ca03b18dd4a729fcf8dd57d6e2faad02a9612c4 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 15:44:53 -0600 Subject: [PATCH 31/45] Add code voice --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8e3e4cd..6c89630 100644 --- a/README.md +++ b/README.md @@ -71,19 +71,19 @@ The following table summarizes the arithmetic limits for Julian day number calcu | Calendar | Minimum JDN | Maximum JDN | | --- | --- | --- | -| Armenian | Int.min + 341 | Int.max - 317 | -| Baháʼí | Int.min + 56457 | 2305795661307959248 | -| Coptic | Int.min + 384 | 2305843009213693827 | -| Egyptian | Int.min + 611 | Int.max - 47 | -| Ethiopian | Int.min + 384 | 2305843009213693827 | -| French Republican | Int.min + 56759 | 2305795661307960548 | -| Gregorian | Int.min + 56457 | 2305795661307959247 | -| Hebrew | Int.min + 106960181 | 355839970905570 | -| Islamic | Int.min + 325 | 307445734561818195 | -| Julian | Int.min + 144 | 2305843009213692550 | -| Khwarizmian | Int.min + 341 | Int.max - 317 | -| Maya Long Count | Int.min + 584291 | Int.max | -| Śaka | Int.min + 56457 | 2305795661307959298 | +| Armenian | `Int.min` + 341 | `Int.max` - 317 | +| Baháʼí | `Int.min` + 56457 | 2305795661307959248 | +| Coptic | `Int.min` + 384 | 2305843009213693827 | +| Egyptian | `Int.min` + 611 | `Int.max` - 47 | +| Ethiopian | `Int.min` + 384 | 2305843009213693827 | +| French Republican | `Int.min` + 56759 | 2305795661307960548 | +| Gregorian | `Int.min` + 56457 | 2305795661307959247 | +| Hebrew | `Int.min` + 106960181 | 355839970905570 | +| Islamic | `Int.min` + 325 | 307445734561818195 | +| Julian | `Int.min` + 144 | 2305843009213692550 | +| Khwarizmian | `Int.min` + 341 | `Int.max` - 317 | +| Maya Long Count | `Int.min` + 584291 | `Int.max` | +| Śaka | `Int.min` + 56457 | 2305795661307959298 | ## License From 96f80a111ab84ce3c7e05cc7460d99ad136ef95d Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 15:47:33 -0600 Subject: [PATCH 32/45] Add grouping --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6c89630..8950509 100644 --- a/README.md +++ b/README.md @@ -72,18 +72,18 @@ The following table summarizes the arithmetic limits for Julian day number calcu | Calendar | Minimum JDN | Maximum JDN | | --- | --- | --- | | Armenian | `Int.min` + 341 | `Int.max` - 317 | -| Baháʼí | `Int.min` + 56457 | 2305795661307959248 | -| Coptic | `Int.min` + 384 | 2305843009213693827 | +| Baháʼí | `Int.min` + 56,457 | 2,305,795,661,307,959,248 | +| Coptic | `Int.min` + 384 | 2,305,843,009,213,693,827 | | Egyptian | `Int.min` + 611 | `Int.max` - 47 | -| Ethiopian | `Int.min` + 384 | 2305843009213693827 | -| French Republican | `Int.min` + 56759 | 2305795661307960548 | -| Gregorian | `Int.min` + 56457 | 2305795661307959247 | -| Hebrew | `Int.min` + 106960181 | 355839970905570 | -| Islamic | `Int.min` + 325 | 307445734561818195 | -| Julian | `Int.min` + 144 | 2305843009213692550 | +| Ethiopian | `Int.min` + 384 | 2,305,843,009,213,693,827 | +| French Republican | `Int.min` + 56759 | 2,305,795,661,307,960,548 | +| Gregorian | `Int.min` + 56,457 | 2,305,795,661,307,959,247 | +| Hebrew | `Int.min` + 106,960,181 | 355,839,970,905,570 | +| Islamic | `Int.min` + 325 | 307,445,734,561,818,195 | +| Julian | `Int.min` + 144 | 2,305,843,009,213,692,550 | | Khwarizmian | `Int.min` + 341 | `Int.max` - 317 | -| Maya Long Count | `Int.min` + 584291 | `Int.max` | -| Śaka | `Int.min` + 56457 | 2305795661307959298 | +| Maya Long Count | `Int.min` + 584,291 | `Int.max` | +| Śaka | `Int.min` + 56,457 | 2,305,795,661,307,959,298 | ## License From 08e6bfb1aa412762f03e903fda7319ea8e73d64b Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 15:48:35 -0600 Subject: [PATCH 33/45] Add grouping --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8950509..4635063 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ The following table summarizes the arithmetic limits for Julian day number calcu | Coptic | `Int.min` + 384 | 2,305,843,009,213,693,827 | | Egyptian | `Int.min` + 611 | `Int.max` - 47 | | Ethiopian | `Int.min` + 384 | 2,305,843,009,213,693,827 | -| French Republican | `Int.min` + 56759 | 2,305,795,661,307,960,548 | +| French Republican | `Int.min` + 56,759 | 2,305,795,661,307,960,548 | | Gregorian | `Int.min` + 56,457 | 2,305,795,661,307,959,247 | | Hebrew | `Int.min` + 106,960,181 | 355,839,970,905,570 | | Islamic | `Int.min` + 325 | 307,445,734,561,818,195 | From a429e7ffc7c3af888a419014337bab2d5f247be2 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 15:50:10 -0600 Subject: [PATCH 34/45] Revert "Add grouping" This reverts commit 08e6bfb1aa412762f03e903fda7319ea8e73d64b. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4635063..8950509 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ The following table summarizes the arithmetic limits for Julian day number calcu | Coptic | `Int.min` + 384 | 2,305,843,009,213,693,827 | | Egyptian | `Int.min` + 611 | `Int.max` - 47 | | Ethiopian | `Int.min` + 384 | 2,305,843,009,213,693,827 | -| French Republican | `Int.min` + 56,759 | 2,305,795,661,307,960,548 | +| French Republican | `Int.min` + 56759 | 2,305,795,661,307,960,548 | | Gregorian | `Int.min` + 56,457 | 2,305,795,661,307,959,247 | | Hebrew | `Int.min` + 106,960,181 | 355,839,970,905,570 | | Islamic | `Int.min` + 325 | 307,445,734,561,818,195 | From d631a82c0e0ac9d0b662b3f595d53552d31e66ca Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 15:50:27 -0600 Subject: [PATCH 35/45] Revert "Add grouping" This reverts commit 96f80a111ab84ce3c7e05cc7460d99ad136ef95d. --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8950509..6c89630 100644 --- a/README.md +++ b/README.md @@ -72,18 +72,18 @@ The following table summarizes the arithmetic limits for Julian day number calcu | Calendar | Minimum JDN | Maximum JDN | | --- | --- | --- | | Armenian | `Int.min` + 341 | `Int.max` - 317 | -| Baháʼí | `Int.min` + 56,457 | 2,305,795,661,307,959,248 | -| Coptic | `Int.min` + 384 | 2,305,843,009,213,693,827 | +| Baháʼí | `Int.min` + 56457 | 2305795661307959248 | +| Coptic | `Int.min` + 384 | 2305843009213693827 | | Egyptian | `Int.min` + 611 | `Int.max` - 47 | -| Ethiopian | `Int.min` + 384 | 2,305,843,009,213,693,827 | -| French Republican | `Int.min` + 56759 | 2,305,795,661,307,960,548 | -| Gregorian | `Int.min` + 56,457 | 2,305,795,661,307,959,247 | -| Hebrew | `Int.min` + 106,960,181 | 355,839,970,905,570 | -| Islamic | `Int.min` + 325 | 307,445,734,561,818,195 | -| Julian | `Int.min` + 144 | 2,305,843,009,213,692,550 | +| Ethiopian | `Int.min` + 384 | 2305843009213693827 | +| French Republican | `Int.min` + 56759 | 2305795661307960548 | +| Gregorian | `Int.min` + 56457 | 2305795661307959247 | +| Hebrew | `Int.min` + 106960181 | 355839970905570 | +| Islamic | `Int.min` + 325 | 307445734561818195 | +| Julian | `Int.min` + 144 | 2305843009213692550 | | Khwarizmian | `Int.min` + 341 | `Int.max` - 317 | -| Maya Long Count | `Int.min` + 584,291 | `Int.max` | -| Śaka | `Int.min` + 56,457 | 2,305,795,661,307,959,298 | +| Maya Long Count | `Int.min` + 584291 | `Int.max` | +| Śaka | `Int.min` + 56457 | 2305795661307959298 | ## License From fc621c6f8ed33a46fed4bd19fb20dc056bdb0c63 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 15:57:36 -0600 Subject: [PATCH 36/45] Move parameters declarations --- Sources/JulianDayNumber/SakaCalendar.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/JulianDayNumber/SakaCalendar.swift b/Sources/JulianDayNumber/SakaCalendar.swift index dac04b2..a24fed2 100644 --- a/Sources/JulianDayNumber/SakaCalendar.swift +++ b/Sources/JulianDayNumber/SakaCalendar.swift @@ -135,6 +135,12 @@ extension SakaCalendar: JulianDayNumberConverting { /// A date in the Śaka calendar consists of a year, month, and day. public typealias DateType = (year: Int, month: Int, day: Int) + /// Algorithm parameters for Śaka calendar conversions. + static let conversionParameters = JDNConversionParameters(y: 4794, j: 1348, m: 1, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 31, t: 0, w: 0) + + /// Gregorian intercalating parameters for Śaka calendar conversions. + static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274073, C: -36) + public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { var Y = date.year var ΔcalendarCycles = 0 @@ -191,10 +197,4 @@ extension SakaCalendar: JulianDayNumberConverting { return (Y, M, D) } - - /// Algorithm parameters for Śaka calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4794, j: 1348, m: 1, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 31, t: 0, w: 0) - - /// Gregorian intercalating parameters for Śaka calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274073, C: -36) } From c222b54a958023f038142750b45237189ef8044d Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 18:13:53 -0600 Subject: [PATCH 37/45] Refactor algorithms --- .../JulianDayNumber/ArmenianCalendar.swift | 8 +- Sources/JulianDayNumber/BahaiCalendar.swift | 11 +- Sources/JulianDayNumber/CopticCalendar.swift | 8 +- .../JulianDayNumber/EgyptianCalendar.swift | 8 +- .../JulianDayNumber/EthiopianCalendar.swift | 8 +- .../FrenchRepublicanCalendar.swift | 11 +- .../JulianDayNumber/GregorianCalendar.swift | 11 +- Sources/JulianDayNumber/IslamicCalendar.swift | 8 +- Sources/JulianDayNumber/JulianCalendar.swift | 8 +- .../JulianDayNumberConverter.swift | 101 ++++++++++ .../JulianDayNumberConverting.swift | 176 ------------------ ...ulianDayNumberGregorianTypeConverter.swift | 108 +++++++++++ .../JulianDayNumberSakaConverter.swift | 109 +++++++++++ .../JulianDayNumber/KhwarizmianCalendar.swift | 8 +- Sources/JulianDayNumber/SakaCalendar.swift | 62 +----- 15 files changed, 362 insertions(+), 283 deletions(-) create mode 100644 Sources/JulianDayNumber/JulianDayNumberConverter.swift create mode 100644 Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift create mode 100644 Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift diff --git a/Sources/JulianDayNumber/ArmenianCalendar.swift b/Sources/JulianDayNumber/ArmenianCalendar.swift index 9c7e052..f4ad7b0 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar.swift @@ -83,14 +83,14 @@ extension ArmenianCalendar: JulianDayNumberConverting { /// A date in the Armenian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Armenian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + /// The converter for the Armenian calendar. + static let converter = JulianDayNumberConverter(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/BahaiCalendar.swift b/Sources/JulianDayNumber/BahaiCalendar.swift index e198aab..e0d760d 100644 --- a/Sources/JulianDayNumber/BahaiCalendar.swift +++ b/Sources/JulianDayNumber/BahaiCalendar.swift @@ -139,17 +139,14 @@ extension BahaiCalendar: JulianDayNumberConverting { /// A date in the Baháʼí calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Baháʼí calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0) - - /// Gregorian intercalating parameters for Baháʼí calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274273, C: -50) + /// The converter for the Baháʼí calendar. + static let converter = JulianDayNumberGregorianTypeConverter(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0, A: 184, B: 274273, C: -50) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/CopticCalendar.swift b/Sources/JulianDayNumber/CopticCalendar.swift index d5399c9..9232876 100644 --- a/Sources/JulianDayNumber/CopticCalendar.swift +++ b/Sources/JulianDayNumber/CopticCalendar.swift @@ -100,14 +100,14 @@ extension CopticCalendar: JulianDayNumberConverting { /// A date in the Coptic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Coptic calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + /// The converter for the Coptic calendar. + static let converter = JulianDayNumberConverter(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/EgyptianCalendar.swift b/Sources/JulianDayNumber/EgyptianCalendar.swift index 58058fb..5263b48 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar.swift @@ -84,14 +84,14 @@ extension EgyptianCalendar: JulianDayNumberConverting { /// A date in the Egyptian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Egyptian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + /// The converter for the Egyptian calendar. + static let converter = JulianDayNumberConverter(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/EthiopianCalendar.swift b/Sources/JulianDayNumber/EthiopianCalendar.swift index eafe7f6..22aca22 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar.swift @@ -100,14 +100,14 @@ extension EthiopianCalendar: JulianDayNumberConverting { /// A date in the Ethiopian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Ethiopian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + /// The converter for the Ethiopian calendar. + static let converter = JulianDayNumberConverter(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift index a9a2470..145b66f 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift @@ -137,17 +137,14 @@ extension FrenchRepublicanCalendar: JulianDayNumberConverting { /// A date in the French Republican calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for French Republican calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) - - /// Gregorian intercalating parameters for French Republican calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 396, B: 578797, C: -51) + /// The converter for the French Republican calendar. + static let converter = JulianDayNumberGregorianTypeConverter(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0, A: 396, B: 578797, C: -51) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/GregorianCalendar.swift b/Sources/JulianDayNumber/GregorianCalendar.swift index ebcba6b..60d29b0 100644 --- a/Sources/JulianDayNumber/GregorianCalendar.swift +++ b/Sources/JulianDayNumber/GregorianCalendar.swift @@ -178,17 +178,14 @@ extension GregorianCalendar: JulianDayNumberConverting { /// A date in the Gregorian calendar consists of a year, month, and day. public typealias DateType = JulianCalendar.DateType - /// Algorithm parameters for Gregorian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) - - /// Gregorian intercalating parameters for Gregorian calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274277, C: -38) + /// The converter for the Gregorian calendar. + static let converter = JulianDayNumberGregorianTypeConverter(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2, A: 184, B: 274277, C: -38) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters, gregorianIntercalatingParameters: gregorianIntercalatingParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/IslamicCalendar.swift b/Sources/JulianDayNumber/IslamicCalendar.swift index 4aae375..6a1f179 100644 --- a/Sources/JulianDayNumber/IslamicCalendar.swift +++ b/Sources/JulianDayNumber/IslamicCalendar.swift @@ -102,14 +102,14 @@ extension IslamicCalendar: JulianDayNumberConverting { /// A date in the Islamic calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Islamic calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) + /// The converter for the Islamic calendar. + static let converter = JulianDayNumberConverter(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/JulianCalendar.swift b/Sources/JulianDayNumber/JulianCalendar.swift index 3c02cfb..5891c30 100644 --- a/Sources/JulianDayNumber/JulianCalendar.swift +++ b/Sources/JulianDayNumber/JulianCalendar.swift @@ -158,14 +158,14 @@ extension JulianCalendar: JulianDayNumberConverting { /// A date in the Julian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Julian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) + /// The converter for the Julian calendar. + static let converter = JulianDayNumberConverter(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/JulianDayNumberConverter.swift b/Sources/JulianDayNumber/JulianDayNumberConverter.swift new file mode 100644 index 0000000..d69bef3 --- /dev/null +++ b/Sources/JulianDayNumber/JulianDayNumberConverter.swift @@ -0,0 +1,101 @@ +// +// Copyright © 2021-2023 Stephen F. Booth +// Part of https://github.com/sbooth/JulianDayNumber +// MIT license +// + +import Foundation + +// + +/// A converter implementing algorithms for interconverting a Julian day number and a year, month, and day. +/// +/// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," +/// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), +/// Chapter 15, pp. 585-624. +struct JulianDayNumberConverter { + /// A date consisting of a year, month, and day. + typealias YearMonthDay = (year: Int, month: Int, day: Int) + + /// The number of years in the computational calendar which precede the epoch. + let y: Int + /// The number of days the epoch of the computational calendar (0/0/0) precedes day zero. + let j: Int + /// The month number which corresponds to month zero in the computational calendar. + let m: Int + /// The number of months in a year, counting any epagonomai as an extra month. + let n: Int + /// The number of years in an intercalation cycle. + let r: Int + /// The number of days in an intercalation cycle. + let p: Int + let q: Int + let v: Int + let u: Int + let s: Int + let t: Int + let w: Int + + /// Converts a date to a Julian day numberand returns the result. + /// + /// - important: No validation checks are performed on the date values. + /// + /// - parameter date: A date to convert. + /// + /// - returns: The Julian day number corresponding to the specified date. + func julianDayNumberFromDate(_ date: YearMonthDay) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if Y <= -y { + ΔcalendarCycles = (-y - Y) / r + 1 + Y += ΔcalendarCycles * r + } + + let h = date.month - m + let g = Y + y - (n - h) / n + let f = (h - 1 + n) % n + let e = (p * g + q) / r + date.day - 1 - j + var J = e + (s * f + t) / u + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * p + } + + return J + } + + /// Converts a Julian day number to a date and returns the result. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The date corresponding to the specified Julian day number. + func dateFromJulianDayNumber(_ J: JulianDayNumber) -> YearMonthDay { +// precondition(J < Int.max - 1) + + var J = J + var ΔcalendarCycles = 0 + + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / p + 1 + J += ΔcalendarCycles * p + } + + precondition(J <= Int.max - j, "Julian day number too large") + + let f = J + j + let e = r * f + v + let g = (e % p) / r + let h = u * g + w + let D = (h % s) / u + 1 + let M = ((h / s + m) % n) + 1 + var Y = e / p - y + (n + m - M) / n + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * r + } + + return (Y, M, D) + } +} diff --git a/Sources/JulianDayNumber/JulianDayNumberConverting.swift b/Sources/JulianDayNumber/JulianDayNumberConverting.swift index 786f882..1ed1384 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverting.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverting.swift @@ -53,182 +53,6 @@ extension JulianDayNumberConverting where DateType == (year: Int, month: Int, da } } -// MARK: - Conversion Algorithms - -// Algorithms adapted from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -/// Algorithm parameters for converting a Julian day number to a year, month, and day. -struct JDNConversionParameters { - /// The number of years in the computational calendar which precede the epoch. - let y: Int - /// The number of days the epoch of the computational calendar (0/0/0) precedes day zero. - let j: Int - /// The month number which corresponds to month zero in the computational calendar. - let m: Int - /// The number of months in a year, counting any epagonomai as an extra month. - let n: Int - /// The number of years in an intercalation cycle. - let r: Int - /// The number of days in an intercalation cycle. - let p: Int - let q: Int - let v: Int - let u: Int - let s: Int - let t: Int - let w: Int -} - -/// Algorithm parameters specific to calenders using Gregorian-type intercalating. -struct JDNGregorianIntercalatingParameters { - let A: Int - let B: Int - let C: Int -} - -/// A calendar's intercalating cycle. -typealias IntercalatingCycle = (years: Int, days: Int) - -/// A date consisting of a year, month, and day. -typealias YearMonthDay = (year: Int, month: Int, day: Int) - -/// Converts a date to a Julian day number using the specified conversion parameters and returns the result. -/// -/// - important: No validation checks are performed on the date values. -/// -/// - parameter date: A date to convert. -/// - parameter parameters: Parameters for the conversion algorithm. -/// -/// - returns: The Julian day number corresponding to the specified date. -func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - if Y <= -parameters.y { - ΔcalendarCycles = (-parameters.y - Y) / parameters.r + 1 - Y += ΔcalendarCycles * parameters.r - } - - let h = date.month - parameters.m - let g = Y + parameters.y - (parameters.n - h) / parameters.n - let f = (h - 1 + parameters.n) % parameters.n - let e = (parameters.p * g + parameters.q) / parameters.r + date.day - 1 - parameters.j - var J = e + (parameters.s * f + parameters.t) / parameters.u - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * parameters.p - } - - return J -} - -/// Converts a Julian day number to a date and returns the result. -/// -/// - parameter J: A Julian day number. -/// - parameter parameters: Parameters for the conversion algorithm. -/// -/// - returns: The date corresponding to the specified Julian day number. -func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters) -> YearMonthDay { -// precondition(J < Int.max - 1) - - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / parameters.p + 1 - J += ΔcalendarCycles * parameters.p - } - - precondition(J <= Int.max - parameters.j, "Julian day number too large") - - let f = J + parameters.j - let e = parameters.r * f + parameters.v - let g = (e % parameters.p) / parameters.r - let h = parameters.u * g + parameters.w - let D = (h % parameters.s) / parameters.u + 1 - let M = ((h / parameters.s + parameters.m) % parameters.n) + 1 - var Y = e / parameters.p - parameters.y + (parameters.n + parameters.m - M) / parameters.n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * parameters.r - } - - return (Y, M, D) -} - -// TODO: Figure out a way to use the Gregorian intercalating parameters A, B and C instead - -/// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. -let gregorianIntercalatingCycle = (years: 400, days: 146097) - -/// Converts a date to a Julian day number using the specified conversion parameters and returns the result. -/// -/// - important: No validation checks are performed on the date values. -/// -/// - parameter date: A date to convert. -/// - parameter parameters: Parameters for the conversion algorithm. -/// - parameter gregorianIntercalatingParameters: Parameters for Gregorian-type intercalating. -/// -/// - returns: The Julian day number corresponding to the specified date. -func jdnFromDate(_ date: YearMonthDay, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - if Y <= -parameters.y { - ΔcalendarCycles = (-parameters.y - Y) / gregorianIntercalatingCycle.years + 1 - Y += ΔcalendarCycles * gregorianIntercalatingCycle.years - } - - let h = date.month - parameters.m - let g = Y + parameters.y - (parameters.n - h) / parameters.n - let f = (h - 1 + parameters.n) % parameters.n - let e = (parameters.p * g + parameters.q) / parameters.r + date.day - 1 - parameters.j - var J = e + (parameters.s * f + parameters.t) / parameters.u - J = J - (3 * ((g + gregorianIntercalatingParameters.A) / 100)) / 4 - gregorianIntercalatingParameters.C - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * gregorianIntercalatingCycle.days - } - - return J -} - -/// Converts a Julian day number to a date and returns the result. -/// -/// - parameter J: A Julian day number. -/// - parameter parameters: Parameters for the conversion algorithm. -/// - parameter gregorianIntercalatingParameters: Parameters for Gregorian-type intercalating. -/// -/// - returns: The date corresponding to the specified Julian day number. -func dateFromJDN(_ J: JulianDayNumber, conversionParameters parameters: JDNConversionParameters, gregorianIntercalatingParameters: JDNGregorianIntercalatingParameters) -> YearMonthDay { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / gregorianIntercalatingCycle.days + 1 - J += ΔcalendarCycles * gregorianIntercalatingCycle.days - } - - precondition(J <= Int.max - parameters.j, "Julian day number too large") - - var f = J + parameters.j - f = f + (((4 * J + gregorianIntercalatingParameters.B) / 146097) * 3) / 4 + gregorianIntercalatingParameters.C - let e = parameters.r * f + parameters.v - let g = (e % parameters.p) / parameters.r - let h = parameters.u * g + parameters.w - let D = (h % parameters.s) / parameters.u + 1 - let M = ((h / parameters.s + parameters.m) % parameters.n) + 1 - var Y = e / parameters.p - parameters.y + (parameters.n + parameters.m - M) / parameters.n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * gregorianIntercalatingCycle.years - } - - return (Y, M, D) -} - // MARK: - Julian Date /// A Julian date. diff --git a/Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift b/Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift new file mode 100644 index 0000000..5d51c63 --- /dev/null +++ b/Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift @@ -0,0 +1,108 @@ +// +// Copyright © 2021-2023 Stephen F. Booth +// Part of https://github.com/sbooth/JulianDayNumber +// MIT license +// + +import Foundation + +// TODO: Figure out a way to use the Gregorian intercalating parameters A, B and C instead + +/// The intercalating cycle of the Gregorian calendar is 303 common years of 365 days and 97 leap years of 366 days. +let gregorianIntercalatingCycle = (years: 400, days: 146097) + +/// A converter implementing algorithms for interconverting a Julian day number and a year, month, and day in calendars using Gregorian-type intercalating. +/// +/// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," +/// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), +/// Chapter 15, pp. 585-624. +struct JulianDayNumberGregorianTypeConverter { + /// A date consisting of a year, month, and day. + typealias YearMonthDay = (year: Int, month: Int, day: Int) + + /// The number of years in the computational calendar which precede the epoch. + let y: Int + /// The number of days the epoch of the computational calendar (0/0/0) precedes day zero. + let j: Int + /// The month number which corresponds to month zero in the computational calendar. + let m: Int + /// The number of months in a year, counting any epagonomai as an extra month. + let n: Int + /// The number of years in an intercalation cycle. + let r: Int + /// The number of days in an intercalation cycle. + let p: Int + let q: Int + let v: Int + let u: Int + let s: Int + let t: Int + let w: Int + + let A: Int + let B: Int + let C: Int + + /// Converts a date to a Julian day number and returns the result. + /// + /// - important: No validation checks are performed on the date values. + /// + /// - parameter date: A date to convert. + /// + /// - returns: The Julian day number corresponding to the specified date. + func julianDayNumberFromDate(_ date: YearMonthDay) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if Y <= -y { + ΔcalendarCycles = (-y - Y) / gregorianIntercalatingCycle.years + 1 + Y += ΔcalendarCycles * gregorianIntercalatingCycle.years + } + + let h = date.month - m + let g = Y + y - (n - h) / n + let f = (h - 1 + n) % n + let e = (p * g + q) / r + date.day - 1 - j + var J = e + (s * f + t) / u + J = J - (3 * ((g + A) / 100)) / 4 - C + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * gregorianIntercalatingCycle.days + } + + return J + } + + /// Converts a Julian day number to a date and returns the result. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The date corresponding to the specified Julian day number. + func dateFromJulianDayNumber(_ J: JulianDayNumber) -> YearMonthDay { + var J = J + var ΔcalendarCycles = 0 + + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / gregorianIntercalatingCycle.days + 1 + J += ΔcalendarCycles * gregorianIntercalatingCycle.days + } + + precondition(J <= Int.max - j, "Julian day number too large") + + var f = J + j + f = f + (((4 * J + B) / 146097) * 3) / 4 + C + let e = r * f + v + let g = (e % p) / r + let h = u * g + w + let D = (h % s) / u + 1 + let M = ((h / s + m) % n) + 1 + var Y = e / p - y + (n + m - M) / n + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * gregorianIntercalatingCycle.years + } + + return (Y, M, D) + } +} diff --git a/Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift b/Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift new file mode 100644 index 0000000..a165a1e --- /dev/null +++ b/Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift @@ -0,0 +1,109 @@ +// +// Copyright © 2021-2023 Stephen F. Booth +// Part of https://github.com/sbooth/JulianDayNumber +// MIT license +// + +import Foundation + +/// A converter implementing algorithms for interconverting a Julian day number and a year, month, and day in the Śaka calendar. +/// +/// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," +/// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), +/// Chapter 15, pp. 585-624. +struct JulianDayNumberSakaConverter { + /// A date consisting of a year, month, and day. + typealias YearMonthDay = (year: Int, month: Int, day: Int) + + /// The number of years in the computational calendar which precede the epoch. + let y = 4794 + /// The number of days the epoch of the computational calendar (0/0/0) precedes day zero. + let j = 1348 + /// The month number which corresponds to month zero in the computational calendar. + let m = 1 + /// The number of months in a year, counting any epagonomai as an extra month. + let n = 12 + /// The number of years in an intercalation cycle. + let r = 4 + /// The number of days in an intercalation cycle. + let p = 1461 + let q = 0 + let v = 3 + let u = 1 + let s = 31 + let t = 0 + let w = 0 + + let A = 184 + let B = 274073 + let C = -36 + + /// Converts a date in the Śaka calendar to a Julian day number and returns the result. + /// + /// - important: No validation checks are performed on the date values. + /// + /// - parameter date: A date to convert. + /// + /// - returns: The Julian day number corresponding to the specified date. + func julianDayNumberFromDate(_ date: YearMonthDay) -> JulianDayNumber { + var Y = date.year + var ΔcalendarCycles = 0 + + if Y <= -y { + ΔcalendarCycles = (-y - Y) / gregorianIntercalatingCycle.years + 1 + Y += ΔcalendarCycles * gregorianIntercalatingCycle.years + } + + let h = date.month - m + let g = Y + y - (n - h) / n + let f = (h - 1 + n) % n + let e = (p * g + q) / r + date.day - 1 - j + let Z = f / 6 + var J = e + ((31 - Z) * f + 5 * Z) / u + J = J - (3 * ((g + A) / 100)) / 4 - C + + if ΔcalendarCycles > 0 { + J -= ΔcalendarCycles * gregorianIntercalatingCycle.days + } + + return J + } + + /// Converts a Julian day number to a date in the Śaka calendar and returns the result. + /// + /// - parameter J: A Julian day number. + /// + /// - returns: The date corresponding to the specified Julian day number. + func dateFromJulianDayNumber(_ J: JulianDayNumber) -> YearMonthDay { + var J = J + var ΔcalendarCycles = 0 + + // Richards' algorithm is only valid for positive JDNs. + if J < 0 { + ΔcalendarCycles = -J / gregorianIntercalatingCycle.days + 1 + J += ΔcalendarCycles * gregorianIntercalatingCycle.days + } + + precondition(J <= Int.max - j, "Julian day number too large") + + var f = J + j + f = f + (((4 * J + B) / 146097) * 3) / 4 + C + let e = r * f + v + let g = (e % p) / r + let X = g / 365 + let Z = g / 185 - X + let s = 31 - Z + let w = -5 * Z + let h = u * g + w + let D = (6 * X + (h % s)) / u + 1 + + let M = ((h / s + m) % n) + 1 + var Y = e / p - y + (n + m - M) / n + + if ΔcalendarCycles > 0 { + Y -= ΔcalendarCycles * gregorianIntercalatingCycle.years + } + + return (Y, M, D) + } +} diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar.swift b/Sources/JulianDayNumber/KhwarizmianCalendar.swift index e493be4..e3906ab 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar.swift @@ -83,14 +83,14 @@ extension KhwarizmianCalendar: JulianDayNumberConverting { /// A date in the Khwarizmian calendar consists of a year, month, and day. public typealias DateType = (year: Year, month: Month, day: Day) - /// Algorithm parameters for Khwarizmian calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + /// The converter for the Khwarizmian calendar. + static let converter = JulianDayNumberConverter(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - jdnFromDate(date, conversionParameters: conversionParameters) + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - dateFromJDN(J, conversionParameters: conversionParameters) + converter.dateFromJulianDayNumber(J) } } diff --git a/Sources/JulianDayNumber/SakaCalendar.swift b/Sources/JulianDayNumber/SakaCalendar.swift index a24fed2..abc2cab 100644 --- a/Sources/JulianDayNumber/SakaCalendar.swift +++ b/Sources/JulianDayNumber/SakaCalendar.swift @@ -129,72 +129,18 @@ public struct SakaCalendar { } } -// Algorithm adapted from the Explanatory Supplement to the Astronomical Almanac, 3rd edition, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - extension SakaCalendar: JulianDayNumberConverting { /// A date in the Śaka calendar consists of a year, month, and day. public typealias DateType = (year: Int, month: Int, day: Int) - /// Algorithm parameters for Śaka calendar conversions. - static let conversionParameters = JDNConversionParameters(y: 4794, j: 1348, m: 1, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 31, t: 0, w: 0) - - /// Gregorian intercalating parameters for Śaka calendar conversions. - static let gregorianIntercalatingParameters = JDNGregorianIntercalatingParameters(A: 184, B: 274073, C: -36) + /// The converter for the Śaka calendar. + static let converter = JulianDayNumberSakaConverter() public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { - var Y = date.year - var ΔcalendarCycles = 0 - - if Y <= -conversionParameters.y { - ΔcalendarCycles = (-conversionParameters.y - Y) / gregorianIntercalatingCycle.years + 1 - Y += ΔcalendarCycles * gregorianIntercalatingCycle.years - } - - let h = date.month - conversionParameters.m - let g = Y + conversionParameters.y - (conversionParameters.n - h) / conversionParameters.n - let f = (h - 1 + conversionParameters.n) % conversionParameters.n - let e = (conversionParameters.p * g + conversionParameters.q) / conversionParameters.r + date.day - 1 - conversionParameters.j - let Z = f / 6 - var J = e + ((31 - Z) * f + 5 * Z) / conversionParameters.u - J = J - (3 * ((g + gregorianIntercalatingParameters.A) / 100)) / 4 - gregorianIntercalatingParameters.C - - if ΔcalendarCycles > 0 { - J -= ΔcalendarCycles * gregorianIntercalatingCycle.days - } - - return J + converter.julianDayNumberFromDate(date) } public static func dateFromJulianDayNumber(_ J: JulianDayNumber) -> DateType { - var J = J - var ΔcalendarCycles = 0 - - // Richards' algorithm is only valid for positive JDNs. - if J < 0 { - ΔcalendarCycles = -J / gregorianIntercalatingCycle.days + 1 - J += ΔcalendarCycles * gregorianIntercalatingCycle.days - } - - precondition(J <= Int.max - conversionParameters.j, "Julian day number too large") - - var f = J + conversionParameters.j - f = f + (((4 * J + gregorianIntercalatingParameters.B) / 146097) * 3) / 4 + gregorianIntercalatingParameters.C - let e = conversionParameters.r * f + conversionParameters.v - let g = (e % conversionParameters.p) / conversionParameters.r - let X = g / 365 - let Z = g / 185 - X - let s = 31 - Z - let w = -5 * Z - let h = conversionParameters.u * g + w - let D = (6 * X + (h % s)) / conversionParameters.u + 1 - - let M = ((h / s + conversionParameters.m) % conversionParameters.n) + 1 - var Y = e / conversionParameters.p - conversionParameters.y + (conversionParameters.n + conversionParameters.m - M) / conversionParameters.n - - if ΔcalendarCycles > 0 { - Y -= ΔcalendarCycles * gregorianIntercalatingCycle.years - } - - return (Y, M, D) + converter.dateFromJulianDayNumber(J) } } From 7860a6184b4cec24940f49a53af0894aa426687a Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 19:45:47 -0600 Subject: [PATCH 38/45] Remove extraneous comment --- Sources/JulianDayNumber/JulianDayNumberConverter.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Sources/JulianDayNumber/JulianDayNumberConverter.swift b/Sources/JulianDayNumber/JulianDayNumberConverter.swift index d69bef3..ddcf009 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverter.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverter.swift @@ -6,8 +6,6 @@ import Foundation -// - /// A converter implementing algorithms for interconverting a Julian day number and a year, month, and day. /// /// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," From 45643dd49f3529859f199a19a604b6842fd8c453 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 20:32:40 -0600 Subject: [PATCH 39/45] Expand comment --- Sources/JulianDayNumber/JulianDayNumberConverter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JulianDayNumber/JulianDayNumberConverter.swift b/Sources/JulianDayNumber/JulianDayNumberConverter.swift index ddcf009..f219c06 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverter.swift +++ b/Sources/JulianDayNumber/JulianDayNumberConverter.swift @@ -6,7 +6,7 @@ import Foundation -/// A converter implementing algorithms for interconverting a Julian day number and a year, month, and day. +/// A converter implementing algorithms for interconverting a Julian day number and a year, month, and day for selected arithmetic calendars. /// /// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," /// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), From 10c5cec69678d7cbdea3bf62337737800b81a8d1 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 20:34:15 -0600 Subject: [PATCH 40/45] Minor edits --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6c89630..11facae 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fsbooth%2FJulianDayNumber%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/sbooth/JulianDayNumber) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fsbooth%2FJulianDayNumber%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/sbooth/JulianDayNumber) -Julian day number (JDN) and Julian date (JD) calculations supporting the following calendars: +Julian day number and Julian date calculations supporting the following calendars: - [Armenian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/armeniancalendar) - [Astronomical](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/astronomicalcalendar) - [Baháʼí](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/bahaicalendar) @@ -19,9 +19,7 @@ Julian day number (JDN) and Julian date (JD) calculations supporting the followi - [Maya](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/mayacalendar) - [Śaka](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/sakacalendar) -Most of the JDN conversion algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), Chapter 15, pp. 585-624. - -The JDN algorithms use integer math to avoid rounding errors and the implementations have been round-trip tested for all valid Julian day numbers in the years -999,999 to +999,999. +The Julian day number interconverting algorithms use integer math to avoid rounding errors and the implementations have been round-trip tested for all valid Julian day numbers in the years -999,999 to +999,999. ## Installation From 9f65808a076a39057c93729e8543479f3f1cd830 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 20:57:02 -0600 Subject: [PATCH 41/45] Reword description --- Sources/JulianDayNumber/EgyptianCalendar.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JulianDayNumber/EgyptianCalendar.swift b/Sources/JulianDayNumber/EgyptianCalendar.swift index 5263b48..f3e7a4f 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar.swift @@ -6,7 +6,7 @@ import Foundation -/// The Egyptian calendar is a solar calendar with 365 days in every year. +/// The Egyptian calendar is a solar calendar with 365 days in the year. /// /// The year consists of twelve months having 30 days each. The twelfth month is followed by five epagomenal days. /// From b3682883d5c78c4431cfe9a09ad69af8ecfeffa7 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 20:57:15 -0600 Subject: [PATCH 42/45] Add more calendar information --- README.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 11facae..f87e94e 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,24 @@ [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fsbooth%2FJulianDayNumber%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/sbooth/JulianDayNumber) Julian day number and Julian date calculations supporting the following calendars: -- [Armenian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/armeniancalendar) -- [Astronomical](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/astronomicalcalendar) -- [Baháʼí](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/bahaicalendar) -- [Coptic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/copticcalendar) -- [Egyptian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/egyptiancalendar) -- [Ethiopian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/ethiopiancalendar) -- [French Republican](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/frenchrepublicancalendar) -- [Gregorian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/gregoriancalendar) -- [Hebrew](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/hebrewcalendar) -- [Islamic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/islamiccalendar) -- [Julian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/juliancalendar) -- [Khwarizmian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/khwarizmiancalendar) -- [Maya](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/mayacalendar) -- [Śaka](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/sakacalendar) +| Calendar | Epoch ¹ | Description | +| --- | --- | +| [Armenian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/armeniancalendar) | July 11, 552 CE | A solar calendar with 365 days in the year. | +| [Astronomical](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/astronomicalcalendar) | January 1, 1 CE | A hybrid calendar that uses the Julian calendar for dates before October 15, 1582 and the Gregorian calendar for later dates. | +| [Baháʼí](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/bahaicalendar) | March 21, 1844 | A solar calendar with 365 days in the year plus an additional leap day in certain years. | +| [Coptic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/copticcalendar) | August 29, 284 CE | A solar calendar with 365 days in the year plus an additional leap day every fourth year. | +| [Egyptian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/egyptiancalendar) | February 26, 747 BCE | A solar calendar with 365 days in the year. | +| [Ethiopian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/ethiopiancalendar) | August 29, 8 CE | A solar calendar with 365 days in the year plus an additional leap day every fourth year. | +| [French Republican](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/frenchrepublicancalendar) | September 22, 1792 | An astronomical calendar with 365 days in the year plus an additional leap day in certain years. | +| [Gregorian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/gregoriancalendar) | January 1, 1 CE | A solar calendar with 365 days in the year plus an additional leap day in certain years. | +| [Hebrew](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/hebrewcalendar) | October 7, 3761 BCE | A lunisolar calendar with either 353, 354, 355, 383, 384, or 385 days in the year. | +| [Islamic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/islamiccalendar) | July 16, 622 CE | A lunar calendar with 354 days in the year plus an additional leap day in certain years. | +| [Julian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/juliancalendar) | January 1, 1 CE | A solar calendar with 365 days in the year plus an additional leap day every fourth year. | +| [Khwarizmian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/khwarizmiancalendar) | June 21, 632 CE | A solar calendar with 365 days in the year. | +| [Maya](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/mayacalendar) | September 6, 3114 BCE | A system of calendars consisting of several cycles of different lengths. | +| [Śaka](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/sakacalendar) | March 24, 79 CE | A solar calendar with 365 days in the year plus an additional leap day in certain years. | + +¹ Epochs given in Julian calendar The Julian day number interconverting algorithms use integer math to avoid rounding errors and the implementations have been round-trip tested for all valid Julian day numbers in the years -999,999 to +999,999. From 9765887047672c5b891aaf516beef37e3f0f6e12 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 20:58:51 -0600 Subject: [PATCH 43/45] Fix table --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f87e94e..8968ea6 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fsbooth%2FJulianDayNumber%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/sbooth/JulianDayNumber) Julian day number and Julian date calculations supporting the following calendars: + | Calendar | Epoch ¹ | Description | -| --- | --- | +| --- | --- | --- | | [Armenian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/armeniancalendar) | July 11, 552 CE | A solar calendar with 365 days in the year. | | [Astronomical](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/astronomicalcalendar) | January 1, 1 CE | A hybrid calendar that uses the Julian calendar for dates before October 15, 1582 and the Gregorian calendar for later dates. | | [Baháʼí](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/bahaicalendar) | March 21, 1844 | A solar calendar with 365 days in the year plus an additional leap day in certain years. | From 8001a854850bf94421d42a5cc60201ef850c1764 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 21:03:08 -0600 Subject: [PATCH 44/45] Remove descriptions --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 8968ea6..c160d7d 100644 --- a/README.md +++ b/README.md @@ -5,22 +5,22 @@ Julian day number and Julian date calculations supporting the following calendars: -| Calendar | Epoch ¹ | Description | -| --- | --- | --- | -| [Armenian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/armeniancalendar) | July 11, 552 CE | A solar calendar with 365 days in the year. | -| [Astronomical](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/astronomicalcalendar) | January 1, 1 CE | A hybrid calendar that uses the Julian calendar for dates before October 15, 1582 and the Gregorian calendar for later dates. | -| [Baháʼí](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/bahaicalendar) | March 21, 1844 | A solar calendar with 365 days in the year plus an additional leap day in certain years. | -| [Coptic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/copticcalendar) | August 29, 284 CE | A solar calendar with 365 days in the year plus an additional leap day every fourth year. | -| [Egyptian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/egyptiancalendar) | February 26, 747 BCE | A solar calendar with 365 days in the year. | -| [Ethiopian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/ethiopiancalendar) | August 29, 8 CE | A solar calendar with 365 days in the year plus an additional leap day every fourth year. | -| [French Republican](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/frenchrepublicancalendar) | September 22, 1792 | An astronomical calendar with 365 days in the year plus an additional leap day in certain years. | -| [Gregorian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/gregoriancalendar) | January 1, 1 CE | A solar calendar with 365 days in the year plus an additional leap day in certain years. | -| [Hebrew](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/hebrewcalendar) | October 7, 3761 BCE | A lunisolar calendar with either 353, 354, 355, 383, 384, or 385 days in the year. | -| [Islamic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/islamiccalendar) | July 16, 622 CE | A lunar calendar with 354 days in the year plus an additional leap day in certain years. | -| [Julian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/juliancalendar) | January 1, 1 CE | A solar calendar with 365 days in the year plus an additional leap day every fourth year. | -| [Khwarizmian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/khwarizmiancalendar) | June 21, 632 CE | A solar calendar with 365 days in the year. | -| [Maya](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/mayacalendar) | September 6, 3114 BCE | A system of calendars consisting of several cycles of different lengths. | -| [Śaka](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/sakacalendar) | March 24, 79 CE | A solar calendar with 365 days in the year plus an additional leap day in certain years. | +| Calendar | Epoch ¹ | +| --- | --- | +| [Armenian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/armeniancalendar) | July 11, 552 CE | +| [Astronomical](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/astronomicalcalendar) | January 1, 1 CE | +| [Baháʼí](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/bahaicalendar) | March 21, 1844 | +| [Coptic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/copticcalendar) | August 29, 284 CE | year. | +| [Egyptian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/egyptiancalendar) | February 26, 747 BCE | +| [Ethiopian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/ethiopiancalendar) | August 29, 8 CE | +| [French Republican](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/frenchrepublicancalendar) | September 22, 1792 | +| [Gregorian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/gregoriancalendar) | January 1, 1 CE | +| [Hebrew](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/hebrewcalendar) | October 7, 3761 BCE | +| [Islamic](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/islamiccalendar) | July 16, 622 CE | +| [Julian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/juliancalendar) | January 1, 1 CE | +| [Khwarizmian](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/khwarizmiancalendar) | June 21, 632 CE | +| [Maya](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/mayacalendar) | September 6, 3114 BCE | +| [Śaka](https://swiftpackageindex.com/sbooth/juliandaynumber/main/documentation/juliandaynumber/sakacalendar) | March 24, 79 CE | ¹ Epochs given in Julian calendar From 8c3eed01cfb7babe4c9eb3523ffe7cc42aac53e7 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 15 Nov 2023 21:11:07 -0600 Subject: [PATCH 45/45] Rename converters --- Sources/JulianDayNumber/ArmenianCalendar.swift | 2 +- Sources/JulianDayNumber/BahaiCalendar.swift | 2 +- Sources/JulianDayNumber/CopticCalendar.swift | 2 +- Sources/JulianDayNumber/EgyptianCalendar.swift | 2 +- Sources/JulianDayNumber/EthiopianCalendar.swift | 2 +- Sources/JulianDayNumber/FrenchRepublicanCalendar.swift | 2 +- Sources/JulianDayNumber/GregorianCalendar.swift | 2 +- Sources/JulianDayNumber/IslamicCalendar.swift | 2 +- .../{JulianDayNumberConverter.swift => JDNConverter.swift} | 2 +- ...orianTypeConverter.swift => JDNGregorianTypeConverter.swift} | 2 +- ...ulianDayNumberSakaConverter.swift => JDNSakaConverter.swift} | 2 +- Sources/JulianDayNumber/JulianCalendar.swift | 2 +- Sources/JulianDayNumber/KhwarizmianCalendar.swift | 2 +- Sources/JulianDayNumber/SakaCalendar.swift | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) rename Sources/JulianDayNumber/{JulianDayNumberConverter.swift => JDNConverter.swift} (98%) rename Sources/JulianDayNumber/{JulianDayNumberGregorianTypeConverter.swift => JDNGregorianTypeConverter.swift} (98%) rename Sources/JulianDayNumber/{JulianDayNumberSakaConverter.swift => JDNSakaConverter.swift} (98%) diff --git a/Sources/JulianDayNumber/ArmenianCalendar.swift b/Sources/JulianDayNumber/ArmenianCalendar.swift index f4ad7b0..3ee267e 100644 --- a/Sources/JulianDayNumber/ArmenianCalendar.swift +++ b/Sources/JulianDayNumber/ArmenianCalendar.swift @@ -84,7 +84,7 @@ extension ArmenianCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Armenian calendar. - static let converter = JulianDayNumberConverter(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + static let converter = JDNConverter(y: 5268, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/BahaiCalendar.swift b/Sources/JulianDayNumber/BahaiCalendar.swift index e0d760d..5c58b0b 100644 --- a/Sources/JulianDayNumber/BahaiCalendar.swift +++ b/Sources/JulianDayNumber/BahaiCalendar.swift @@ -140,7 +140,7 @@ extension BahaiCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Baháʼí calendar. - static let converter = JulianDayNumberGregorianTypeConverter(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0, A: 184, B: 274273, C: -50) + static let converter = JDNGregorianTypeConverter(y: 6560, j: 1412, m: 19, n: 20, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 19, t: 0, w: 0, A: 184, B: 274273, C: -50) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/CopticCalendar.swift b/Sources/JulianDayNumber/CopticCalendar.swift index 9232876..49bd6de 100644 --- a/Sources/JulianDayNumber/CopticCalendar.swift +++ b/Sources/JulianDayNumber/CopticCalendar.swift @@ -101,7 +101,7 @@ extension CopticCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Coptic calendar. - static let converter = JulianDayNumberConverter(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + static let converter = JDNConverter(y: 4996, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/EgyptianCalendar.swift b/Sources/JulianDayNumber/EgyptianCalendar.swift index f3e7a4f..3889499 100644 --- a/Sources/JulianDayNumber/EgyptianCalendar.swift +++ b/Sources/JulianDayNumber/EgyptianCalendar.swift @@ -85,7 +85,7 @@ extension EgyptianCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Egyptian calendar. - static let converter = JulianDayNumberConverter(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + static let converter = JDNConverter(y: 3968, j: 47, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/EthiopianCalendar.swift b/Sources/JulianDayNumber/EthiopianCalendar.swift index 22aca22..b803547 100644 --- a/Sources/JulianDayNumber/EthiopianCalendar.swift +++ b/Sources/JulianDayNumber/EthiopianCalendar.swift @@ -101,7 +101,7 @@ extension EthiopianCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Ethiopian calendar. - static let converter = JulianDayNumberConverter(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) + static let converter = JDNConverter(y: 4720, j: 124, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift index 145b66f..e98af4d 100644 --- a/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift +++ b/Sources/JulianDayNumber/FrenchRepublicanCalendar.swift @@ -138,7 +138,7 @@ extension FrenchRepublicanCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the French Republican calendar. - static let converter = JulianDayNumberGregorianTypeConverter(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0, A: 396, B: 578797, C: -51) + static let converter = JDNGregorianTypeConverter(y: 6504, j: 111, m: 0, n: 13, r: 4, p: 1461, q: 0, v: 3, u: 1, s: 30, t: 0, w: 0, A: 396, B: 578797, C: -51) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/GregorianCalendar.swift b/Sources/JulianDayNumber/GregorianCalendar.swift index 60d29b0..755fe84 100644 --- a/Sources/JulianDayNumber/GregorianCalendar.swift +++ b/Sources/JulianDayNumber/GregorianCalendar.swift @@ -179,7 +179,7 @@ extension GregorianCalendar: JulianDayNumberConverting { public typealias DateType = JulianCalendar.DateType /// The converter for the Gregorian calendar. - static let converter = JulianDayNumberGregorianTypeConverter(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2, A: 184, B: 274277, C: -38) + static let converter = JDNGregorianTypeConverter(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2, A: 184, B: 274277, C: -38) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/IslamicCalendar.swift b/Sources/JulianDayNumber/IslamicCalendar.swift index 6a1f179..44b6af2 100644 --- a/Sources/JulianDayNumber/IslamicCalendar.swift +++ b/Sources/JulianDayNumber/IslamicCalendar.swift @@ -103,7 +103,7 @@ extension IslamicCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Islamic calendar. - static let converter = JulianDayNumberConverter(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) + static let converter = JDNConverter(y: 5519, j: 7664, m: 0, n: 12, r: 30, p: 10631, q: 14, v: 15, u: 100, s: 2951, t: 51, w: 10) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/JulianDayNumberConverter.swift b/Sources/JulianDayNumber/JDNConverter.swift similarity index 98% rename from Sources/JulianDayNumber/JulianDayNumberConverter.swift rename to Sources/JulianDayNumber/JDNConverter.swift index f219c06..c8bf580 100644 --- a/Sources/JulianDayNumber/JulianDayNumberConverter.swift +++ b/Sources/JulianDayNumber/JDNConverter.swift @@ -11,7 +11,7 @@ import Foundation /// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," /// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), /// Chapter 15, pp. 585-624. -struct JulianDayNumberConverter { +struct JDNConverter { /// A date consisting of a year, month, and day. typealias YearMonthDay = (year: Int, month: Int, day: Int) diff --git a/Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift b/Sources/JulianDayNumber/JDNGregorianTypeConverter.swift similarity index 98% rename from Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift rename to Sources/JulianDayNumber/JDNGregorianTypeConverter.swift index 5d51c63..9173c05 100644 --- a/Sources/JulianDayNumber/JulianDayNumberGregorianTypeConverter.swift +++ b/Sources/JulianDayNumber/JDNGregorianTypeConverter.swift @@ -16,7 +16,7 @@ let gregorianIntercalatingCycle = (years: 400, days: 146097) /// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," /// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), /// Chapter 15, pp. 585-624. -struct JulianDayNumberGregorianTypeConverter { +struct JDNGregorianTypeConverter { /// A date consisting of a year, month, and day. typealias YearMonthDay = (year: Int, month: Int, day: Int) diff --git a/Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift b/Sources/JulianDayNumber/JDNSakaConverter.swift similarity index 98% rename from Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift rename to Sources/JulianDayNumber/JDNSakaConverter.swift index a165a1e..77a8132 100644 --- a/Sources/JulianDayNumber/JulianDayNumberSakaConverter.swift +++ b/Sources/JulianDayNumber/JDNSakaConverter.swift @@ -11,7 +11,7 @@ import Foundation /// The algorithms are adapted from Richards, E.G. 2012, "[Calendars](https://aa.usno.navy.mil/downloads/c15_usb_online.pdf)," /// from the *Explanatory Supplement to the Astronomical Almanac, 3rd edition*, S.E Urban and P.K. Seidelmann eds., (Mill Valley, CA: University Science Books), /// Chapter 15, pp. 585-624. -struct JulianDayNumberSakaConverter { +struct JDNSakaConverter { /// A date consisting of a year, month, and day. typealias YearMonthDay = (year: Int, month: Int, day: Int) diff --git a/Sources/JulianDayNumber/JulianCalendar.swift b/Sources/JulianDayNumber/JulianCalendar.swift index 5891c30..aa89e49 100644 --- a/Sources/JulianDayNumber/JulianCalendar.swift +++ b/Sources/JulianDayNumber/JulianCalendar.swift @@ -159,7 +159,7 @@ extension JulianCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Julian calendar. - static let converter = JulianDayNumberConverter(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) + static let converter = JDNConverter(y: 4716, j: 1401, m: 2, n: 12, r: 4, p: 1461, q: 0, v: 3, u: 5, s: 153, t: 2, w: 2) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/KhwarizmianCalendar.swift b/Sources/JulianDayNumber/KhwarizmianCalendar.swift index e3906ab..55f12e5 100644 --- a/Sources/JulianDayNumber/KhwarizmianCalendar.swift +++ b/Sources/JulianDayNumber/KhwarizmianCalendar.swift @@ -84,7 +84,7 @@ extension KhwarizmianCalendar: JulianDayNumberConverting { public typealias DateType = (year: Year, month: Month, day: Day) /// The converter for the Khwarizmian calendar. - static let converter = JulianDayNumberConverter(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) + static let converter = JDNConverter(y: 5348, j: 317, m: 0, n: 13, r: 1, p: 365, q: 0, v: 0, u: 1, s: 30, t: 0, w: 0) public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date) diff --git a/Sources/JulianDayNumber/SakaCalendar.swift b/Sources/JulianDayNumber/SakaCalendar.swift index abc2cab..44a976f 100644 --- a/Sources/JulianDayNumber/SakaCalendar.swift +++ b/Sources/JulianDayNumber/SakaCalendar.swift @@ -134,7 +134,7 @@ extension SakaCalendar: JulianDayNumberConverting { public typealias DateType = (year: Int, month: Int, day: Int) /// The converter for the Śaka calendar. - static let converter = JulianDayNumberSakaConverter() + static let converter = JDNSakaConverter() public static func julianDayNumberFromDate(_ date: DateType) -> JulianDayNumber { converter.julianDayNumberFromDate(date)