Packages/MoonriseKit/Sources/SkyEngine/MarsTime.swift
45 lines · 1794 bytes
1import Foundation
2
3/// Mars Coordinated Time and rover local times, after NASA GISS Mars24 (Allison & McEwen 2000).
4public enum MarsTime {
5 public struct Rover: Sendable, Identifiable {
6 public var name: String
7 public var site: String
8 /// East longitude in degrees.
9 public var longitude: Double
10 /// Mars Sol Date of the landing sol's local midnight (sol 0).
11 public var landingSol: Int
12 public var id: String { name }
13
14 public static let active: [Rover] = [
15 Rover(name: "Perseverance", site: "Jezero Crater", longitude: 77.45, landingSol: 52304),
16 Rover(name: "Curiosity", site: "Gale Crater", longitude: 137.44, landingSol: 49269),
17 ]
18 }
19
20 /// TT − UTC: 32.184 s plus 37 leap seconds (none since 2017).
21 static let ttMinusUTC = 69.184
22
23 /// Mars Sol Date.
24 public static func msd(_ date: Date) -> Double {
25 let jdTT = (date.timeIntervalSince1970 + ttMinusUTC) / 86_400 + 2_440_587.5
26 return (jdTT - 2_405_522.0028779) / 1.0274912517
27 }
28
29 /// Local mean solar time in hours (0..<24) at an east longitude.
30 public static func localMeanTime(_ date: Date, eastLongitude: Double) -> Double {
31 let mtc = (msd(date) * 24).truncatingRemainder(dividingBy: 24)
32 let t = (mtc + eastLongitude / 15).truncatingRemainder(dividingBy: 24)
33 return t < 0 ? t + 24 : t
34 }
35
36 /// Mission sol number (sol 0 is the landing sol).
37 public static func sol(_ date: Date, rover: Rover) -> Int {
38 Int((msd(date) + rover.longitude / 360).rounded(.down)) - rover.landingSol
39 }
40
41 public static func format(hours: Double) -> String {
42 let total = Int(hours * 60)
43 return String(format: "%02d:%02d", total / 60 % 24, total % 60)
44 }
45}