tea_time/impls/
impl_ops.rs1use std::ops::{Add, Div, Mul, Neg, Sub};
2
3use chrono::{DateTime as CrDateTime, Months, Utc};
4
5use crate::{DateTime, Time, TimeDelta, TimeUnitTrait};
6
7impl<U: TimeUnitTrait> Add<TimeDelta> for DateTime<U>
10where
11 Self: From<CrDateTime<Utc>> + TryInto<CrDateTime<Utc>>,
12{
13 type Output = DateTime<U>;
14 fn add(self, rhs: TimeDelta) -> Self::Output {
15 if self.is_not_nat() && rhs.is_not_nat() {
16 let dt = self.as_cr().unwrap();
17 let out = if rhs.months != 0 {
18 if rhs.months > 0 {
19 dt + Months::new(rhs.months as u32)
20 } else {
21 dt - Months::new((-rhs.months) as u32)
22 }
23 } else {
24 dt
25 };
26 (out + rhs.inner).into()
27 } else {
28 DateTime::nat()
29 }
30 }
31}
32
33impl<U: TimeUnitTrait> Sub<TimeDelta> for DateTime<U>
34where
35 Self: From<CrDateTime<Utc>> + TryInto<CrDateTime<Utc>>,
36{
37 type Output = DateTime<U>;
38 fn sub(self, rhs: TimeDelta) -> Self::Output {
39 if self.is_not_nat() && rhs.is_not_nat() {
40 let dt = self.as_cr().unwrap();
41 let out = if rhs.months != 0 {
42 if rhs.months > 0 {
43 dt - Months::new(rhs.months as u32)
44 } else {
45 dt + Months::new((-rhs.months) as u32)
46 }
47 } else {
48 dt
49 };
50 (out - rhs.inner).into()
51 } else {
52 DateTime::nat()
53 }
54 }
55}
56
57impl<U: TimeUnitTrait> Sub<DateTime<U>> for DateTime<U>
58where
59 Self: From<CrDateTime<Utc>> + TryInto<CrDateTime<Utc>>,
60{
61 type Output = TimeDelta;
62 fn sub(self, rhs: DateTime<U>) -> Self::Output {
63 if self.is_not_nat() && rhs.is_not_nat() {
66 let dt1 = self.as_cr().unwrap();
67 let dt2 = rhs.as_cr().unwrap();
68 let duration = dt1 - dt2;
69 TimeDelta {
70 months: 0,
71 inner: duration,
72 }
73 } else {
83 TimeDelta::nat()
84 }
85 }
86}
87
88impl Neg for TimeDelta {
89 type Output = TimeDelta;
90
91 #[inline]
92 fn neg(self) -> TimeDelta {
93 if self.is_not_nat() {
94 Self {
95 months: -self.months,
96 inner: -self.inner,
97 }
98 } else {
99 self
100 }
101 }
102}
103
104impl Add for TimeDelta {
105 type Output = TimeDelta;
106 #[inline]
107 fn add(self, rhs: TimeDelta) -> TimeDelta {
108 if self.is_not_nat() & rhs.is_not_nat() {
109 Self {
110 months: self.months + rhs.months,
111 inner: self.inner + rhs.inner,
112 }
113 } else {
114 TimeDelta::nat()
115 }
116 }
117}
118
119impl Sub for TimeDelta {
120 type Output = TimeDelta;
121 #[inline]
122 fn sub(self, rhs: TimeDelta) -> TimeDelta {
123 if self.is_not_nat() & rhs.is_not_nat() {
124 Self {
125 months: self.months - rhs.months,
126 inner: self.inner - rhs.inner,
127 }
128 } else {
129 TimeDelta::nat()
130 }
131 }
132}
133
134impl Mul<i32> for TimeDelta {
135 type Output = TimeDelta;
136 #[inline]
137 fn mul(self, rhs: i32) -> Self {
138 if self.is_not_nat() {
139 Self {
140 months: self.months * rhs,
141 inner: self.inner * rhs,
142 }
143 } else {
144 TimeDelta::nat()
145 }
146 }
147}
148
149impl Div<TimeDelta> for TimeDelta {
150 type Output = i32;
151
152 fn div(self, rhs: TimeDelta) -> Self::Output {
153 if self.is_not_nat() & rhs.is_not_nat() {
154 let inner_div =
156 self.inner.num_nanoseconds().unwrap() / rhs.inner.num_nanoseconds().unwrap();
157 if self.months == 0 || rhs.months == 0 {
158 return inner_div as i32;
159 }
160 let month_div = self.months / rhs.months;
161 if month_div == inner_div as i32 {
162 month_div
163 } else {
164 panic!("not support div TimeDelta when month div and time div is not equal")
165 }
166 } else {
167 panic!("not support div TimeDelta when one of them is nat")
168 }
169 }
170}
171
172impl Add<TimeDelta> for Time {
173 type Output = Time;
174 fn add(self, rhs: TimeDelta) -> Self::Output {
175 if rhs.is_not_nat() {
176 if rhs.months != 0 {
177 panic!("not support add TimeDelta with months");
178 }
179 if let Some(nanos) = rhs.inner.num_nanoseconds() {
180 let nanos = self.0 + nanos;
181 return Time(nanos);
182 }
183 }
184 Time::nat()
185 }
186}
187
188impl Sub<TimeDelta> for Time {
189 type Output = Time;
190 fn sub(self, rhs: TimeDelta) -> Self::Output {
191 if rhs.is_not_nat() {
192 if rhs.months != 0 {
193 panic!("not support sub TimeDelta with months");
194 }
195 if let Some(nanos) = rhs.inner.num_nanoseconds() {
196 let nanos = self.0 - nanos;
197 return Time(nanos);
198 }
199 }
200 Time::nat()
201 }
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207 use crate::TimeDelta;
208
209 #[test]
210 fn test_time_add_timedelta() {
211 let time = Time::from_hms(12, 0, 0);
212 let delta = TimeDelta::parse("1h30m").unwrap();
213 let result = time + delta;
214 assert_eq!(result, Time::from_hms(13, 30, 0));
215 }
216
217 #[test]
218 fn test_time_sub_timedelta() {
219 let time = Time::from_hms(12, 0, 0);
220 let delta = TimeDelta::parse("1h30m").unwrap();
221 let result = time - delta;
222 assert_eq!(result, Time::from_hms(10, 30, 0));
223 }
224
225 #[test]
226 #[should_panic]
227 fn test_time_add_timedelta_with_months() {
228 let time = Time::from_hms(12, 0, 0);
229 let delta = TimeDelta::parse("1mo1h30m").unwrap();
230 let _ = time + delta;
231 }
232
233 #[test]
234 #[should_panic]
235 fn test_time_sub_timedelta_with_months() {
236 let time = Time::from_hms(12, 0, 0);
237 let delta = TimeDelta::parse("1mo1h30m").unwrap();
238 let _ = time - delta;
239 }
240
241 #[test]
242 fn test_time_add_nat_timedelta() {
243 let time = Time::from_hms(12, 0, 0);
244 let nat_delta = TimeDelta::nat();
245 let result = time + nat_delta;
246 assert_eq!(result, Time::nat());
247 }
248
249 #[test]
250 fn test_time_sub_nat_timedelta() {
251 let time = Time::from_hms(12, 0, 0);
252 let nat_delta = TimeDelta::nat();
253 let result = time - nat_delta;
254 assert_eq!(result, Time::nat());
255 }
256}