deep_time/time_parts/
to_jiff.rs1use {
2 crate::{
3 ATTOS_PER_NS, Meridiem, Offset, TimeParts, Weekday, an_err,
4 error::{DtErr, DtErrKind},
5 },
6 alloc::string::String,
7 core::result::Result,
8 jiff::{
9 Timestamp, Zoned,
10 fmt::strtime::{BrokenDownTime, Meridiem as JiffMeridiem},
11 tz::Offset as JiffOffset,
12 },
13};
14
15impl TimeParts {
16 pub fn to_jiff_broken_down_time(&self) -> Result<BrokenDownTime, DtErr> {
18 let mut bdt = BrokenDownTime::default();
19
20 if let Some(year) = self.yr {
22 let y: i16 = year
23 .try_into()
24 .map_err(|e| an_err!(DtErrKind::InvalidInput, "year: {}: {}", year, e))?;
25 bdt.set_year(Some(y))
26 .map_err(|e| an_err!(DtErrKind::InvalidItem, "year: {}: {}", y, e))?;
27 }
28 if let Some(m) = self.mo {
29 bdt.set_month(Some(m as i8))
30 .map_err(|e| an_err!(DtErrKind::InvalidItem, "month: {}: {}", m, e))?;
31 }
32 if let Some(d) = self.day {
33 bdt.set_day(Some(d as i8))
34 .map_err(|e| an_err!(DtErrKind::InvalidItem, "day: {}: {}", d, e))?;
35 }
36
37 if let Some(doy) = self.day_of_yr {
39 bdt.set_day_of_year(Some(doy as i16))
40 .map_err(|e| an_err!(DtErrKind::InvalidItem, "doy: {}: {}", doy, e))?;
41 }
42 if let Some(y) = self.iso_wk_yr {
43 let y: i16 = y
44 .try_into()
45 .map_err(|e| an_err!(DtErrKind::InvalidInput, "iso wk yr: {}: {}", y, e))?;
46 bdt.set_iso_week_year(Some(y))
47 .map_err(|e| an_err!(DtErrKind::InvalidItem, "iso wk yr: {}: {}", y, e))?;
48 }
49 if let Some(w) = self.iso_wk {
50 bdt.set_iso_week(Some(w as i8))
51 .map_err(|e| an_err!(DtErrKind::InvalidItem, "iso wk: {}: {}", w, e))?;
52 }
53 if let Some(w) = self.wk_sun {
54 bdt.set_sunday_based_week(Some(w as i8))
55 .map_err(|e| an_err!(DtErrKind::InvalidItem, "sun based wk: {}: {}", w, e))?;
56 }
57 if let Some(w) = self.wk_mon {
58 bdt.set_monday_based_week(Some(w as i8))
59 .map_err(|e| an_err!(DtErrKind::InvalidItem, "mon based wk: {}: {}", w, e))?;
60 }
61
62 bdt.set_hour(Some(self.hr as i8))
64 .map_err(|e| an_err!(DtErrKind::InvalidItem, "hour: {}: {}", self.hr, e))?;
65 bdt.set_minute(Some(self.min as i8))
66 .map_err(|e| an_err!(DtErrKind::InvalidItem, "minute: {}: {}", self.min, e))?;
67 let non_ls_s = if self.sec == 60 { 59 } else { self.sec };
68 bdt.set_second(Some(non_ls_s as i8))
69 .map_err(|e| an_err!(DtErrKind::InvalidItem, "second: {}: {}", non_ls_s, e))?;
70
71 if self.attos != 0 {
73 let ns_u64 = self.attos / ATTOS_PER_NS;
74 let ns: i32 = if ns_u64 >= 1_000_000_000 {
75 999_999_999
76 } else {
77 ns_u64 as i32
78 };
79 bdt.set_subsec_nanosecond(Some(ns))
80 .map_err(|e| an_err!(DtErrKind::InvalidItem, "ns: {}: {}", ns, e))?;
81 }
82
83 if let Some(wd) = self.wkday {
85 let jwd = match wd {
86 Weekday::Sunday => jiff::civil::Weekday::Sunday,
87 Weekday::Monday => jiff::civil::Weekday::Monday,
88 Weekday::Tuesday => jiff::civil::Weekday::Tuesday,
89 Weekday::Wednesday => jiff::civil::Weekday::Wednesday,
90 Weekday::Thursday => jiff::civil::Weekday::Thursday,
91 Weekday::Friday => jiff::civil::Weekday::Friday,
92 Weekday::Saturday => jiff::civil::Weekday::Saturday,
93 };
94 bdt.set_weekday(Some(jwd));
95 }
96 if let Some(mer) = self.meridiem {
97 let jmer = match mer {
98 Meridiem::AM => JiffMeridiem::AM,
99 Meridiem::PM => JiffMeridiem::PM,
100 };
101 bdt.set_meridiem(Some(jmer));
102 }
103
104 if let Some(secs) = self.unix_timestamp_seconds {
106 let ts = Timestamp::from_second(secs)
107 .map_err(|e| an_err!(DtErrKind::InvalidInput, "timestamp: {}: {}", secs, e))?;
108 bdt.set_timestamp(Some(ts));
109 }
110
111 if let Some(name) = &self.iana_name {
113 let name_str = name.as_str();
114 if !name_str.is_empty() {
115 bdt.set_iana_time_zone(Some(String::from(name_str)));
116 }
117 } else if let Some(Offset::Fixed(secs)) = self.offset {
118 if let Ok(jiff_offset) = JiffOffset::from_seconds(secs) {
119 bdt.set_offset(Some(jiff_offset));
120 } else {
121 return Err(an_err!(
122 DtErrKind::InvalidTimezoneOffset,
123 "offset secs: {}",
124 secs
125 ));
126 }
127 } else {
128 bdt.set_offset(Some(JiffOffset::UTC));
130 }
131
132 Ok(bdt)
133 }
134
135 pub fn to_jiff_zoned(&self) -> Result<Zoned, DtErr> {
137 let bdt = self.to_jiff_broken_down_time()?;
138 if let Ok(zoned) = bdt.to_zoned() {
139 return Ok(zoned);
140 }
141 if let Ok(ts) = bdt.to_timestamp()
142 && let Ok(zoned) = ts.in_tz("UTC")
143 {
144 return Ok(zoned);
145 }
146 if let Ok(dt) = bdt.to_datetime()
147 && let Ok(zoned) = dt.in_tz("UTC")
148 {
149 return Ok(zoned);
150 }
151 if let Ok(date) = bdt.to_date()
152 && let Ok(dt) = date.at(0, 0, 0, 0).in_tz("UTC")
153 {
154 return Ok(dt);
155 }
156
157 Err(an_err!(
158 DtErrKind::InvalidInput,
159 "could not convert to jiff zoned"
160 ))
161 }
162
163 #[inline(always)]
165 pub fn to_jiff_timestamp(&self) -> Result<Timestamp, DtErr> {
166 self.to_jiff_zoned().map(|z| z.timestamp())
167 }
168}