Skip to content

Commit 9a8218d

Browse files
committed
Update calendars with protocols and add initial roman republican calendar
1 parent 3965040 commit 9a8218d

19 files changed

Lines changed: 8659 additions & 44 deletions

Sources/Calendars/BahaiCalendar.swift

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,42 @@
1919

2020
import Foundation
2121

22-
public struct BahaiCalendar {
22+
public struct BahaiCalendar : CalendarProtocol {
23+
public var calendarId: String { "bahai" }
24+
25+
public func isValidDate(year: Int, month: Int, day: Int) -> Bool {
26+
BahaiCalendar.isValidDate(Y: year, M: month, D: day)
27+
}
28+
29+
public func monthName(forYear year: Int, month: Int) -> String {
30+
precondition(1 <= month && month <= 12)
31+
return BahaiCalendar.nameOfMonth(month)!
32+
}
33+
34+
public func daysInMonth(year: Int, month: Int) -> Int {
35+
BahaiCalendar.daysInMonth(year: year, month: month)
36+
}
37+
38+
public func isProleptic(julianDay jdn: Int) -> Bool {
39+
BahaiCalendar.isProleptic(jdn)
40+
}
41+
42+
public func monthNumber(for month: String, in year: Int) -> Int? {
43+
BahaiCalendar.numberOfMonth(month)
44+
}
45+
46+
public func jdn(forYear year: Int, month: Int, day: Int) -> Int {
47+
BahaiCalendar.toJDN(Y: year, M: month, D: day)
48+
}
49+
50+
public func date(fromJDN jdn: Int) -> (Int, Int, Int) {
51+
BahaiCalendar.toDate(J: jdn)
52+
}
53+
54+
55+
2356
static let epoch = 2394647
57+
static let shared = BahaiCalendar()
2458

2559
public static func isProleptic(_ d: Int) -> Bool {
2660
return d < epoch
@@ -66,3 +100,4 @@ public struct BahaiCalendar {
66100
}
67101

68102
}
103+

Sources/Calendars/CalendarSupport.swift

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,36 +211,42 @@ extension CalendarId {
211211
}
212212
}
213213

214-
215214
extension CalendarId {
216-
public func numberOfMonth(y: Int, m: String) -> Int? {
215+
/// New, year-aware adapter with idiomatic naming.
216+
public func monthNumber(for month: String, in year: Int) -> Int? {
217217
switch self {
218218
case .gregorian:
219-
return GregorianCalendar.numberOfMonth(m)
219+
return GregorianCalendar.numberOfMonth(month)
220220
case .julian:
221-
return JulianCalendar.numberOfMonth(m)
221+
return JulianCalendar.numberOfMonth(month)
222222
case .swedish:
223-
return SwedishCalendar.numberOfMonth(m)
223+
return SwedishCalendar.numberOfMonth(month)
224224
case .frenchRepublican:
225-
return FrenchRepublicanCalendar.numberOfMonth(m)
225+
return FrenchRepublicanCalendar.numberOfMonth(month)
226226
case .jewish:
227-
return JewishCalendar.numberOfMonth(year: y, month: m)
227+
return JewishCalendar.numberOfMonth(year: year, month: month)
228228
case .civilIslamic:
229-
return CivilIslamicCalendar.numberOfMonth(m)
229+
return CivilIslamicCalendar.numberOfMonth(month)
230230
case .saka:
231-
return SakaCalendar.numberOfMonth(m)
231+
return SakaCalendar.numberOfMonth(month)
232232
case .egyptian:
233-
return EgyptianCalendar.numberOfMonth(m)
233+
return EgyptianCalendar.numberOfMonth(month)
234234
case .coptic:
235-
return CopticCalendar.numberOfMonth(m)
235+
return CopticCalendar.numberOfMonth(month)
236236
case .ethiopian:
237-
return EthiopianCalendar.numberOfMonth(m)
237+
return EthiopianCalendar.numberOfMonth(month)
238238
case .bahai:
239-
return BahaiCalendar.numberOfMonth(m)
239+
return BahaiCalendar.numberOfMonth(month)
240240
case .mesoamericanLongCount:
241241
return nil
242242
}
243243
}
244+
245+
/// Deprecated: Use monthNumber(for:in:) instead.
246+
@available(*, deprecated, message: "Use monthNumber(for:in:) instead")
247+
public func numberOfMonth(y: Int, m: String) -> Int? {
248+
return monthNumber(for: m, in: y)
249+
}
244250
}
245251

246252
extension CalendarId {
@@ -275,3 +281,21 @@ extension CalendarId {
275281
}
276282
}
277283

284+
public protocol WeekdayProtocol {
285+
var numberOfDays: Int { get }
286+
func weekday(forYear year: Int, month: Int, day: Int) -> Int
287+
func name(ofWeekday day: Int) -> String
288+
}
289+
290+
public protocol CalendarProtocol: Sendable {
291+
var calendarId: String { get }
292+
293+
func isValidDate(year: Int, month: Int, day: Int) -> Bool
294+
func monthName(forYear year: Int, month: Int) -> String
295+
func daysInMonth(year: Int, month: Int) -> Int
296+
func isProleptic(julianDay jdn: Int) -> Bool
297+
func monthNumber(for month: String, in year: Int) -> Int?
298+
299+
func jdn(forYear year: Int, month: Int, day: Int) -> Int
300+
func date(fromJDN jdn: Int) -> (Int, Int, Int)
301+
}

Sources/Calendars/CivilIslamicCalendar.swift

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,41 @@
1818

1919
import Foundation
2020

21-
public struct CivilIslamicCalendar {
21+
public struct CivilIslamicCalendar : CalendarProtocol {
22+
public var calendarId: String { "civil_islamic" }
23+
24+
public func isValidDate(year: Int, month: Int, day: Int) -> Bool {
25+
CivilIslamicCalendar.isValidDate(Y: year, M: month, D: day)
26+
}
27+
28+
public func monthName(forYear year: Int, month: Int) -> String {
29+
return CivilIslamicCalendar.nameOfMonth(month)
30+
}
31+
32+
public func daysInMonth(year: Int, month: Int) -> Int {
33+
CivilIslamicCalendar.daysInMonth(year: year, month: month)
34+
}
35+
36+
public func isProleptic(julianDay jdn: Int) -> Bool {
37+
CivilIslamicCalendar.isProleptic(jdn)
38+
}
39+
40+
public func monthNumber(for month: String, in year: Int) -> Int? {
41+
CivilIslamicCalendar.numberOfMonth(month)
42+
}
43+
44+
public func jdn(forYear year: Int, month: Int, day: Int) -> Int {
45+
CivilIslamicCalendar.toJDN(Y: year, M: month, D: day)
46+
}
47+
48+
public func date(fromJDN jdn: Int) -> (Int, Int, Int) {
49+
CivilIslamicCalendar.toDate(J: jdn)
50+
}
51+
52+
53+
2254
static let epoch = 1948440
55+
static let shared = CivilIslamicCalendar()
2356

2457
public static func isLeapYear(year: Int) -> Bool {
2558
let yearInCycle = (year - 1) % 30 + 1
@@ -75,3 +108,4 @@ public struct CivilIslamicCalendar {
75108
}
76109

77110
}
111+

Sources/Calendars/CopticCalendar.swift

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,41 @@
1919
import Foundation
2020

2121

22-
public struct CopticCalendar {
22+
public struct CopticCalendar : CalendarProtocol {
23+
public var calendarId: String { "coptic" }
24+
25+
public func isValidDate(year: Int, month: Int, day: Int) -> Bool {
26+
CopticCalendar.isValidDate(Y: year, M: month, D: day)
27+
}
28+
29+
public func monthName(forYear year: Int, month: Int) -> String {
30+
return CopticCalendar.nameOfMonth(month)!
31+
}
32+
33+
public func daysInMonth(year: Int, month: Int) -> Int {
34+
CopticCalendar.daysInMonth(year: year, month: month)
35+
}
36+
37+
public func isProleptic(julianDay jdn: Int) -> Bool {
38+
CopticCalendar.isProleptic(jdn)
39+
}
40+
41+
public func monthNumber(for month: String, in year: Int) -> Int? {
42+
CopticCalendar.numberOfMonth(month)
43+
}
44+
45+
public func jdn(forYear year: Int, month: Int, day: Int) -> Int {
46+
CopticCalendar.toJDN(Y: year, M: month, D: day)
47+
}
48+
49+
public func date(fromJDN jdn: Int) -> (Int, Int, Int) {
50+
CopticCalendar.toDate(J: jdn)
51+
}
52+
53+
54+
2355
static let epoch = 1825030
56+
static let shared = CopticCalendar()
2457

2558
public static func isProleptic(_ d: Int) -> Bool {
2659
return d < epoch
@@ -67,3 +100,4 @@ public struct CopticCalendar {
67100
}
68101

69102
}
103+

Sources/Calendars/DateParser.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public struct DateParser {
5454
let d = Int(match.2)!
5555
let y = Int(match.4)!
5656

57-
if let m = calendar.numberOfMonth(y: y, m: m) {
57+
if let m = calendar.monthNumber(for: m, in: y) {
5858
if calendar.isValidDate(Y: y, M: m, D: d) {
5959
return (y, m, d)
6060
}
@@ -65,7 +65,7 @@ public struct DateParser {
6565
let m = String(match.2)
6666
let y = Int(match.3)!
6767

68-
if let m = calendar.numberOfMonth(y: y, m: m) {
68+
if let m = calendar.monthNumber(for: m, in: y) {
6969
if calendar.isValidDate(Y: y, M: m, D: d) {
7070
return (y, m, d)
7171
}

Sources/Calendars/EgyptianCalendar.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,39 @@
1818

1919
import Foundation
2020

21-
public struct EgyptianCalendar {
21+
public struct EgyptianCalendar : CalendarProtocol {
22+
public var calendarId: String { "egyptian" }
23+
24+
public func isValidDate(year: Int, month: Int, day: Int) -> Bool {
25+
EgyptianCalendar.isValidDate(Y: year, M: month, D: day)
26+
}
27+
28+
public func monthName(forYear year: Int, month: Int) -> String {
29+
return EgyptianCalendar.nameOfMonth(month)
30+
}
31+
32+
public func daysInMonth(year: Int, month: Int) -> Int {
33+
EgyptianCalendar.daysInMonth(year: year, month: month)
34+
}
35+
36+
public func isProleptic(julianDay jdn: Int) -> Bool {
37+
EgyptianCalendar.isProleptic(jdn)
38+
}
39+
40+
public func monthNumber(for month: String, in year: Int) -> Int? {
41+
EgyptianCalendar.numberOfMonth(month)
42+
}
43+
44+
public func jdn(forYear year: Int, month: Int, day: Int) -> Int {
45+
EgyptianCalendar.toJDN(Y: year, M: month, D: day)
46+
}
47+
48+
public func date(fromJDN jdn: Int) -> (Int, Int, Int) {
49+
EgyptianCalendar.toDate(J: jdn)
50+
}
51+
2252
static let epoch = 1448638
53+
static let shared = EgyptianCalendar()
2354

2455
public static func daysInMonth(year: Int, month: Int) -> Int {
2556
if month == 13 {
@@ -68,3 +99,4 @@ public struct EgyptianCalendar {
6899
}
69100

70101
}
102+

Sources/Calendars/EthiopianCalendar.swift

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,40 @@
1818

1919
import Foundation
2020

21-
public struct EthiopianCalendar {
21+
public struct EthiopianCalendar : CalendarProtocol {
22+
public var calendarId: String { "ethiopian" }
23+
24+
public func isValidDate(year: Int, month: Int, day: Int) -> Bool {
25+
EthiopianCalendar.isValidDate(Y: year, M: month, D: day)
26+
}
27+
28+
public func monthName(forYear year: Int, month: Int) -> String {
29+
return EthiopianCalendar.nameOfMonth(month)!
30+
}
31+
32+
public func daysInMonth(year: Int, month: Int) -> Int {
33+
EthiopianCalendar.daysInMonth(year: year, month: month)
34+
}
35+
36+
public func isProleptic(julianDay jdn: Int) -> Bool {
37+
EthiopianCalendar.isProleptic(jdn)
38+
}
39+
40+
public func monthNumber(for month: String, in year: Int) -> Int? {
41+
EthiopianCalendar.numberOfMonth(month)
42+
}
43+
44+
public func jdn(forYear year: Int, month: Int, day: Int) -> Int {
45+
EthiopianCalendar.toJDN(Y: year, M: month, D: day)
46+
}
47+
48+
public func date(fromJDN jdn: Int) -> (Int, Int, Int) {
49+
EthiopianCalendar.toDate(J: jdn)
50+
}
51+
52+
2253
static let epoch = 1724221
54+
static let shared = EthiopianCalendar()
2355

2456
public static func isProleptic(_ d: Int) -> Bool {
2557
return d < epoch
@@ -66,3 +98,4 @@ public struct EthiopianCalendar {
6698
}
6799

68100
}
101+

Sources/Calendars/FrenchRepublicanCalendar.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,39 @@
1818

1919
import Foundation
2020

21-
public struct FrenchRepublicanCalendar {
21+
public struct FrenchRepublicanCalendar : CalendarProtocol {
22+
public var calendarId: String { "french_republican" }
23+
24+
public func isValidDate(year: Int, month: Int, day: Int) -> Bool {
25+
FrenchRepublicanCalendar.isValidDate(Y: year, M: month, D: day)
26+
}
27+
28+
public func monthName(forYear year: Int, month: Int) -> String {
29+
return FrenchRepublicanCalendar.nameOfMonth(month)
30+
}
31+
32+
public func daysInMonth(year: Int, month: Int) -> Int {
33+
FrenchRepublicanCalendar.daysInMonth(year: year, month: month)
34+
}
35+
36+
public func isProleptic(julianDay jdn: Int) -> Bool {
37+
FrenchRepublicanCalendar.isProleptic(jdn)
38+
}
39+
40+
public func monthNumber(for month: String, in year: Int) -> Int? {
41+
FrenchRepublicanCalendar.numberOfMonth(month)
42+
}
43+
44+
public func jdn(forYear year: Int, month: Int, day: Int) -> Int {
45+
FrenchRepublicanCalendar.toJDN(Y: year, M: month, D: day)
46+
}
47+
48+
public func date(fromJDN jdn: Int) -> (Int, Int, Int) {
49+
FrenchRepublicanCalendar.toDate(J: jdn)
50+
}
51+
2252
static let epoch = 2375840
53+
static let shared = FrenchRepublicanCalendar()
2354

2455
public static func nameOfMonth(_ month: Int) -> String {
2556
let monthNames = ["Vendémiaire", "Brumaire", "Frimaire",
@@ -66,3 +97,4 @@ public struct FrenchRepublicanCalendar {
6697
algorithm.toDate(J: J)
6798
}
6899
}
100+

0 commit comments

Comments
 (0)