1use std::fmt;
2use crate::*;
3use chrono::format::*;
4
5pub trait TimeSetFormat {
6 fn format_timeset(&self, timefmt: &str) -> String;
7}
8
9pub trait TimePointFormat {
10 fn format_timepoint(self, timefmt: &str) -> String;
11}
12
13impl TimePointFormat for TimeValue {
14
15 fn format_timepoint(self, _timefmt: &str) -> String {
16 if self.is_positive() {
17 format_duration(self.as_ticks())
18 } else {
19 format!("- {}", &format_duration(-self.as_ticks()))
20 }
21 }
22}
23
24impl TimePointFormat for Timestamp {
25
26 fn format_timepoint(self, timefmt: &str) -> String {
27 format_timestamp(self, timefmt).to_string()
28 }
29}
30
31fn format_duration(t: i64) -> String
32{
33 assert! ( t >= 0 );
34 let mut nanos = TimeValue::from_ticks(t).subsec_nanos();
35 let _remaining_ticks = t - TimeValue::from_nanos(nanos as i64).as_ticks();
36
37 fn concat_unit<F:Fn(i64)->TimeValue>(ticks: (i64,String), convert:F, unit: &str) -> (i64, String)
38 {
39 let x = ticks.0 / (convert)(1).as_ticks();
40 if x == 0 {
41 ticks
42 } else {
43 (ticks.0 - (convert)(x).as_ticks(), format!("{}{}{} ", &ticks.1, x, unit))
44 }
45 }
46 if t == 0 { return "0".to_string(); }
47 let ticks = (t, String::new());
48 let ticks = concat_unit(ticks, TimeValue::from_years, "y");
49 let ticks = concat_unit(ticks, TimeValue::from_months, "mo");
50 let ticks = concat_unit(ticks, TimeValue::from_days, "d");
51 let ticks = concat_unit(ticks, TimeValue::from_hours, "h");
52 let ticks = concat_unit(ticks, TimeValue::from_mins, "min");
53 let ticks = concat_unit(ticks, TimeValue::from_secs, "s");
54
55 let mut str = ticks.1;
56 if nanos > 1_000_000 {
57 str = format!("{}{}ms ", str, nanos/1_000_000);
58 nanos %= 1_000_000;
59 }
60 if nanos > 1_000 {
61 str = format!("{}{}us ", str, nanos/1_000);
62 nanos %= 1_000;
63 }
64 if nanos > 0 {
65 str = format!("{}{}ns ", str, nanos);
66 }
67 if str.pop().is_none() {
75 "0".to_string()
76 } else {
77 str
78 }
79}
80
81fn format_timestamp(t: Timestamp, timefmt: &str) -> DelayedFormat<StrftimeItems<'_>> {
82 t.to_datetime().format(timefmt)
83}
84
85fn format_timeslot<TW:TimeConvex>(tw: &TW, timefmt: &str) -> String
86 where TW::TimePoint: TimePointFormat
87{
88 if tw.is_empty() {
89 "{{}}".to_string()
90
91 } else if tw.is_singleton() {
92 format!("{{{}}}", tw.lower_bound().format_timepoint(timefmt))
93
94 } else if tw.is_low_bounded() {
95 if tw.is_up_bounded() {
96 format!("[{},{}]",tw.lower_bound().format_timepoint(timefmt), tw.upper_bound().format_timepoint(timefmt))
97 } else {
98 format!("[{},+oo[", tw.lower_bound().format_timepoint(timefmt))
99 }
100 } else if tw.is_up_bounded() {
101 format!("]-oo,{}]", tw.upper_bound().format_timepoint(timefmt))
102 } else {
103 "]-oo,+oo[".to_string()
104 }
105}
106
107impl<TW:TimeWindow> TimeSetFormat for TW
108 where TW::TimePoint: TimePointFormat
109{
110 fn format_timeset(&self, timefmt: &str) -> String
111 {
112 let mut iter = self.iter();
113 if let Some(first) = iter.next() {
114 iter.fold(format_timeslot(&first, timefmt),
115 |s,i| s + "U" + &format_timeslot(&i,timefmt))
116 } else {
117 "{{}}".to_string() }
119 }
120}
121
122
123
124impl Debug for TimeValue
125{
126 #[allow(clippy::collapsible_else_if)]
127 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
128 {
129 if self.0 >= 0 {
130 if self.is_future_infinite() {
131 write!(formatter, "+oo")
132 } else {
133 write!(formatter, "{:?}", self.0)
134 }
135 } else {
136 if self.is_past_infinite() {
137 write!(formatter, "-oo")
138 } else {
139 write!(formatter, "{:?}", self.0)
140 }
141 }
142 }
143}
144
145
146impl fmt::Display for TimeValue
147{
148 #[allow(clippy::collapsible_else_if)]
149 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
150 {
151 if self.0 >= 0 {
152 if self.is_future_infinite() {
153 write!(formatter, "+oo")
154 } else {
155 write!(formatter, "{}", format_duration(self.as_ticks()))
156 }
157 } else {
158 if self.is_past_infinite() {
159 write!(formatter, "-oo")
160 } else {
161 write!(formatter, "- {}", format_duration(-self.as_ticks()))
162 }
163 }
164 }
165}
166
167impl fmt::Debug for Timestamp
168{
169 #[inline]
170 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
171 write!(formatter, "t={:?}", self.0)
172 }
173}
174
175impl fmt::Display for Timestamp
176{
177 #[allow(clippy::collapsible_else_if)]
178 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
179 {
180 if self.0.is_positive() {
181 if self.is_future_infinite() {
182 write!(formatter, "+oo")
183 } else {
184 write!(formatter, "{}", self.to_datetime())
185 }
186 } else {
187 if self.is_past_infinite() {
188 write!(formatter, "-oo")
189 } else {
190 write!(formatter, "{} before 1970-01-01 00:00:00 UTC", -self.0)
191 }
192 }
193 }
194}
195
196
197impl<T:TimePoint+fmt::Debug> fmt::Debug for TimeInterval<T>
198{
199 #[allow(clippy::collapsible_else_if)]
200 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
201 {
202 if self.is_low_bounded() {
203 if self.is_up_bounded() {
204 if self.lower == self.upper {
205 write!(formatter, "{{{:?}}}", self.lower)
206 } else {
207 write!(formatter, "[{:?},{:?}]", self.lower, self.upper)
208 }
209 } else {
210 write!(formatter, "[{:?},+oo[", self.lower)
211 }
212 } else {
213 if self.is_up_bounded() {
214 write!(formatter, "]-oo,{:?}]", self.upper)
215 } else {
216 write!(formatter, "]-oo,+oo[")
217 }
218 }
219 }
220}
221
222
223impl<T:TimePoint+fmt::Display> fmt::Display for TimeInterval<T>
224{
225 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
226 {
227 if self.is_empty() {
228 write!(formatter, "{{}}")
229
230 } else if self.is_singleton() {
231 write!(formatter, "{{{}}}", self.lower)
232
233 } else if self.is_low_bounded() {
234 if self.is_up_bounded() {
235 write!(formatter, "[{},{}]", self.lower, self.upper)
236 } else {
237 write!(formatter, "[{},+oo[", self.lower)
238 }
239 } else if self.is_up_bounded() {
240 write!(formatter, "]-oo,{}]", self.upper)
241 } else {
242 write!(formatter, "]-oo,+oo[")
243 }
244 }
245}
246
247
248
249impl<T:TimePoint+fmt::Debug> fmt::Debug for TimeSet<T>
250{
251 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
252 {
253 let mut iter = self.0.iter();
254 if let Some(first) = iter.next() {
255 write!(formatter, "{:?}", first)?;
256 iter.try_for_each(|tw| write!(formatter, "U{:?}", tw))
257 } else {
258 write!(formatter, "{{}}") }
260 }
261}
262
263impl<T:TimePoint+fmt::Display> fmt::Display for TimeSet<T>
264{
265 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result
266 {
267 let mut iter = self.0.iter();
268 if let Some(first) = iter.next() {
269 write!(formatter, "{}", first)?;
270 iter.try_for_each(|tw| write!(formatter, "U{}", tw))
271 } else {
272 write!(formatter, "{{}}") }
274 }
275}