Skip to main content

deep_time/time_parts/
from_str.rs

1use crate::{DtErrKind, DtErr, Offset, TimeParts, an_err, parser::Parser};
2
3impl TimeParts {
4    pub fn from_str(
5        fmt: &str,
6        input: &str,
7        inp_can_end_before_fmt: bool,
8        fmt_can_end_before_inp: bool,
9        allow_partial_date: bool,
10    ) -> Result<TimeParts, DtErr> {
11        let mut tm = TimeParts::new_utc();
12        let mut parser = Parser::new(
13            fmt.as_bytes(),
14            input.as_bytes(),
15            &mut tm,
16            inp_can_end_before_fmt,
17        );
18        if let Err(e) = parser.parse() {
19            return Err(e);
20        }
21        if parser.inp.is_empty() || fmt_can_end_before_inp {
22            // All input consumed → finalize
23            tm.finish(allow_partial_date)?;
24            Ok(tm)
25        } else {
26            // Trailing characters remain
27            Err(an_err!(DtErrKind::TrailingCharacters))
28        }
29    }
30
31    pub fn finish(&mut self, allow_partial_date: bool) -> core::result::Result<&mut Self, DtErr> {
32        if self.unix_timestamp_seconds.is_some() {
33            if self.hour.is_none() {
34                self.hour = Some(0);
35            }
36            if self.minute.is_none() {
37                self.minute = Some(0);
38            }
39            if self.second.is_none() {
40                self.second = Some(0);
41            }
42            if self.attos.is_none() {
43                self.attos = Some(0);
44            }
45            if self.offset.is_none() {
46                self.offset = Some(Offset::Utc);
47            }
48            return Ok(self);
49        }
50
51        // Sensible defaults for time components (most tests expect a full datetime)
52        if self.hour.is_none() {
53            self.hour = Some(0);
54        }
55        if self.minute.is_none() {
56            self.minute = Some(0);
57        }
58        if let Some(sec) = self.second {
59            if sec == 60 {
60                self.is_leap_second = true;
61            } else if sec > 60 {
62                return Err(an_err!(DtErrKind::OutOfRange, "seconds (0..=60): {}", sec));
63            }
64        } else {
65            self.second = Some(0);
66        }
67        if self.attos.is_none() {
68            self.attos = Some(0);
69        }
70        if self.offset.is_none() {
71            self.offset = Some(Offset::Utc);
72        }
73
74        let has_calendar_date = if allow_partial_date {
75            if self.day.is_none() {
76                self.day = Some(1);
77            }
78            if self.month.is_none() {
79                self.month = Some(1);
80            }
81            self.year.is_some()
82        } else {
83            self.year.is_some() && self.month.is_some() && self.day.is_some()
84        };
85        let has_ordinal_date = self.year.is_some() && self.day_of_year.is_some();
86        let has_iso_week_date = self.iso_week_year.is_some() && self.iso_week.is_some();
87
88        if !has_calendar_date && !has_ordinal_date && !has_iso_week_date {
89            return Err(an_err!(DtErrKind::Incomplete));
90        }
91
92        Ok(self)
93    }
94}