Skip to main content

deep_time/time_parts/
mod.rs

1mod from_bin_ccsds;
2mod from_str;
3mod from_str_ccsds;
4mod to_bin_ccsds;
5mod to_deep_time;
6
7#[cfg(feature = "alloc")]
8mod to_str_ccsds;
9
10#[cfg(feature = "chrono")]
11mod to_chrono;
12
13#[cfg(feature = "jiff")]
14mod to_jiff;
15
16use crate::{LiteStr, Scale};
17
18/// A flexible, partially-filled representation of a civil datetime.
19///
20/// [`TimeParts`] is the central intermediate type used throughout the library
21/// for parsing, formatting, and converting between different time representations
22/// (CCSDS, ISO-like strings, `chrono`, `jiff`, `Dt`, etc.).
23///
24/// Most fields are optional, allowing partial dates/times. It also carries
25/// metadata such as the time `scale`, IANA zone name, leap-second flag,
26/// and various weekday/week-number representations.
27///
28/// - Convert to [`Dt`] using [`TimeParts::to_dt`].
29/// - Conversions to types from other crates require relevant features to
30///   be enabled.
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32#[cfg_attr(feature = "js", derive(tsify::Tsify))]
33#[derive(Debug, Clone, Copy, Default, PartialEq)]
34pub struct TimeParts {
35    /// Year (can be negative for BCE dates).
36    pub yr: Option<i64>,
37    /// Month of the year (1–12).
38    pub mo: Option<u8>,
39    /// Day of the month (1–31).
40    pub day: Option<u8>,
41    /// Hour of the day (0–23).
42    pub hr: Option<u8>,
43    /// Minute of the hour (0–59).
44    pub min: Option<u8>,
45    /// Second of the minute (0–60). Value 60 is used for leap seconds.
46    pub sec: Option<u8>,
47    /// Attoseconds (0 ≤ value < 10¹⁸).
48    pub attos: Option<u64>,
49    /// Timezone offset from UTC.
50    pub offset: Option<Offset>,
51    /// IANA timezone name (e.g. `"America/New_York"`), stored as ASCII.
52    pub iana_name: Option<LiteStr<49>>,
53    /// Whether this instant represents a leap second.
54    pub is_leap_sec: bool,
55    /// The time scale this value belongs to (TAI, UTC, etc.).
56    pub scale: Scale,
57    /// Day of the week.
58    pub wkday: Option<Weekday>,
59    /// Day of the year (1–366), corresponding to `%j`.
60    pub day_of_yr: Option<u16>,
61    /// ISO week year (`%G` / `%g`).
62    pub iso_wk_yr: Option<i64>,
63    /// ISO week number (1–53), corresponding to `%V`.
64    pub iso_wk: Option<u8>,
65    /// Week number with Sunday as first day of week (0–53), `%U`.
66    pub wk_sun: Option<u8>,
67    /// Week number with Monday as first day of week (0–53), `%W`.
68    pub wk_mon: Option<u8>,
69    /// AM / PM indicator.
70    pub meridiem: Option<Meridiem>,
71    /// Unix timestamp in seconds (`%s`).
72    pub unix_timestamp_seconds: Option<i64>,
73}
74
75impl TimeParts {
76    #[inline]
77    pub fn new_utc() -> TimeParts {
78        Self {
79            scale: Scale::UTC,
80            ..Default::default()
81        }
82    }
83
84    /// Sets the IANA timezone name.
85    #[inline]
86    pub fn set_iana_name(&mut self, name: Option<&str>) -> &mut Self {
87        self.iana_name = name.map(LiteStr::new);
88        self
89    }
90}
91
92/// AM / PM indicator.
93#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
94#[cfg_attr(feature = "js", derive(tsify::Tsify))]
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
96pub enum Meridiem {
97    #[default]
98    AM,
99    PM,
100}
101
102/// Day of the week. Default is set to Sunday.
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104#[cfg_attr(feature = "js", derive(tsify::Tsify))]
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
106pub enum Weekday {
107    #[default]
108    Sunday,
109    Monday,
110    Tuesday,
111    Wednesday,
112    Thursday,
113    Friday,
114    Saturday,
115}
116
117impl Weekday {
118    /// Converts a Sunday-based weekday number (0 = Sunday … 6 = Saturday) to `Weekday`.
119    pub const fn from_sunday_0_based(n: u8) -> Option<Self> {
120        match n {
121            0 => Some(Weekday::Sunday),
122            1 => Some(Weekday::Monday),
123            2 => Some(Weekday::Tuesday),
124            3 => Some(Weekday::Wednesday),
125            4 => Some(Weekday::Thursday),
126            5 => Some(Weekday::Friday),
127            6 => Some(Weekday::Saturday),
128            _ => None,
129        }
130    }
131
132    /// Converts a Monday-based weekday number (1 = Monday … 7 = Sunday) to `Weekday`.
133    pub const fn from_monday_1_based(n: u8) -> Option<Self> {
134        match n {
135            1 => Some(Weekday::Monday),
136            2 => Some(Weekday::Tuesday),
137            3 => Some(Weekday::Wednesday),
138            4 => Some(Weekday::Thursday),
139            5 => Some(Weekday::Friday),
140            6 => Some(Weekday::Saturday),
141            7 => Some(Weekday::Sunday),
142            _ => None,
143        }
144    }
145
146    /// Sunday-based weekday number (0 = Sunday … 6 = Saturday).
147    pub const fn wkday_sun_0_based(self) -> u8 {
148        match self {
149            Weekday::Sunday => 0,
150            Weekday::Monday => 1,
151            Weekday::Tuesday => 2,
152            Weekday::Wednesday => 3,
153            Weekday::Thursday => 4,
154            Weekday::Friday => 5,
155            Weekday::Saturday => 6,
156        }
157    }
158
159    /// Sunday-based weekday number (1 = Sunday … 7 = Saturday).
160    pub const fn wkday_sun_1_based(self) -> u8 {
161        match self {
162            Weekday::Sunday => 1,
163            Weekday::Monday => 2,
164            Weekday::Tuesday => 3,
165            Weekday::Wednesday => 4,
166            Weekday::Thursday => 5,
167            Weekday::Friday => 6,
168            Weekday::Saturday => 7,
169        }
170    }
171
172    /// Monday-based weekday number (0 = Monday … 6 = Sunday).
173    pub const fn wkday_mon_0_based(self) -> u8 {
174        match self {
175            Weekday::Monday => 0,
176            Weekday::Tuesday => 1,
177            Weekday::Wednesday => 2,
178            Weekday::Thursday => 3,
179            Weekday::Friday => 4,
180            Weekday::Saturday => 5,
181            Weekday::Sunday => 6,
182        }
183    }
184
185    /// Monday-based weekday number (1 = Monday … 7 = Sunday).
186    pub const fn wkday_mon_1_based(self) -> u8 {
187        match self {
188            Weekday::Monday => 1,
189            Weekday::Tuesday => 2,
190            Weekday::Wednesday => 3,
191            Weekday::Thursday => 4,
192            Weekday::Friday => 5,
193            Weekday::Saturday => 6,
194            Weekday::Sunday => 7,
195        }
196    }
197}
198
199/// Timezone offset representation.
200#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
201#[cfg_attr(feature = "js", derive(tsify::Tsify))]
202#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
203pub enum Offset {
204    #[default]
205    Utc,
206    None,
207    /// Fixed offset from UTC in seconds
208    Fixed(i32),
209}