deep_time/time_parts/
from_str.rs1use crate::{DtErr, DtErrKind, 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 parser.parse()?;
19 if parser.inp.is_empty() || fmt_can_end_before_inp {
20 tm.finish(allow_partial_date)?;
22 Ok(tm)
23 } else {
24 Err(an_err!(DtErrKind::TrailingCharacters))
26 }
27 }
28
29 pub fn finish(&mut self, allow_partial_date: bool) -> core::result::Result<&mut Self, DtErr> {
30 if self.unix_timestamp_seconds.is_some() {
31 if self.hour.is_none() {
32 self.hour = Some(0);
33 }
34 if self.minute.is_none() {
35 self.minute = Some(0);
36 }
37 if self.second.is_none() {
38 self.second = Some(0);
39 }
40 if self.attos.is_none() {
41 self.attos = Some(0);
42 }
43 if self.offset.is_none() {
44 self.offset = Some(Offset::Utc);
45 }
46 return Ok(self);
47 }
48
49 if self.hour.is_none() {
51 self.hour = Some(0);
52 }
53 if self.minute.is_none() {
54 self.minute = Some(0);
55 }
56 if let Some(sec) = self.second {
57 if sec == 60 {
58 self.is_leap_second = true;
59 } else if sec > 60 {
60 return Err(an_err!(DtErrKind::OutOfRange, "seconds (0..=60): {}", sec));
61 }
62 } else {
63 self.second = Some(0);
64 }
65 if self.attos.is_none() {
66 self.attos = Some(0);
67 }
68 if self.offset.is_none() {
69 self.offset = Some(Offset::Utc);
70 }
71
72 let has_calendar_date = if allow_partial_date {
73 if self.day.is_none() {
74 self.day = Some(1);
75 }
76 if self.month.is_none() {
77 self.month = Some(1);
78 }
79 self.year.is_some()
80 } else {
81 self.year.is_some() && self.month.is_some() && self.day.is_some()
82 };
83 let has_ordinal_date = self.year.is_some() && self.day_of_year.is_some();
84 let has_iso_week_date = self.iso_week_year.is_some() && self.iso_week.is_some();
85
86 if !has_calendar_date && !has_ordinal_date && !has_iso_week_date {
87 return Err(an_err!(DtErrKind::Incomplete));
88 }
89
90 Ok(self)
91 }
92}