Skip to main content

deep_time/time_parts/
mod.rs

1mod from_ccsds_bin;
2mod from_ccsds_str;
3mod from_str;
4mod to_ccsds_bin;
5mod to_deep_time;
6
7#[cfg(feature = "alloc")]
8mod to_ccsds_str;
9
10#[cfg(feature = "chrono")]
11mod to_chrono;
12
13#[cfg(feature = "jiff")]
14mod to_jiff;
15
16use crate::{AsciiStr, 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<AsciiStr<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() -> Self {
78        Self {
79            scale: Scale::UTC,
80            ..Default::default()
81        }
82    }
83
84    /// Sets the IANA timezone name safely.
85    ///
86    /// Uses `AsciiStr::try_from_str` internally. If the name is non-ASCII
87    /// or longer than 49 bytes it is silently dropped (no panics).
88    #[inline]
89    pub fn set_iana_name(&mut self, name: Option<&str>) -> &mut Self {
90        self.iana_name = name.and_then(|s| AsciiStr::try_from_str(s).ok());
91        self
92    }
93}
94
95/// AM / PM indicator.
96#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
97#[cfg_attr(feature = "js", derive(tsify::Tsify))]
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
99pub enum Meridiem {
100    #[default]
101    AM,
102    PM,
103}
104
105/// Day of the week. Default is set to Sunday.
106#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107#[cfg_attr(feature = "js", derive(tsify::Tsify))]
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
109pub enum Weekday {
110    #[default]
111    Sunday,
112    Monday,
113    Tuesday,
114    Wednesday,
115    Thursday,
116    Friday,
117    Saturday,
118}
119
120impl Weekday {
121    /// Converts a Sunday-based weekday number (0 = Sunday … 6 = Saturday) to `Weekday`.
122    #[inline]
123    pub const fn from_sunday_zero_offset(n: u8) -> Option<Self> {
124        match n {
125            0 => Some(Weekday::Sunday),
126            1 => Some(Weekday::Monday),
127            2 => Some(Weekday::Tuesday),
128            3 => Some(Weekday::Wednesday),
129            4 => Some(Weekday::Thursday),
130            5 => Some(Weekday::Friday),
131            6 => Some(Weekday::Saturday),
132            _ => None,
133        }
134    }
135
136    /// Converts a Monday-based weekday number (1 = Monday … 7 = Sunday) to `Weekday`.
137    #[inline]
138    pub const fn from_monday_one_offset(n: u8) -> Option<Self> {
139        match n {
140            1 => Some(Weekday::Monday),
141            2 => Some(Weekday::Tuesday),
142            3 => Some(Weekday::Wednesday),
143            4 => Some(Weekday::Thursday),
144            5 => Some(Weekday::Friday),
145            6 => Some(Weekday::Saturday),
146            7 => Some(Weekday::Sunday),
147            _ => None,
148        }
149    }
150
151    /// Sunday-based weekday number (0 = Sunday … 6 = Saturday).
152    #[inline]
153    pub const fn wk_sun(self) -> u8 {
154        match self {
155            Weekday::Sunday => 0,
156            Weekday::Monday => 1,
157            Weekday::Tuesday => 2,
158            Weekday::Wednesday => 3,
159            Weekday::Thursday => 4,
160            Weekday::Friday => 5,
161            Weekday::Saturday => 6,
162        }
163    }
164
165    /// Monday-based weekday number (1 = Monday … 7 = Sunday).
166    #[inline]
167    pub const fn wk_mon(self) -> u8 {
168        match self {
169            Weekday::Monday => 1,
170            Weekday::Tuesday => 2,
171            Weekday::Wednesday => 3,
172            Weekday::Thursday => 4,
173            Weekday::Friday => 5,
174            Weekday::Saturday => 6,
175            Weekday::Sunday => 7,
176        }
177    }
178}
179
180/// Timezone offset representation.
181#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
182#[cfg_attr(feature = "js", derive(tsify::Tsify))]
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
184pub enum Offset {
185    #[default]
186    Utc,
187    None,
188    /// Fixed offset from UTC in seconds
189    Fixed(i32),
190}