chronologic/wins/
format.rs

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    /*
68    todo: displaying type with format %t
69    if remaining_ticks != 0 {
70        str = format!("{}{}t ", str, remaining_ticks);
71    }
72    */
73
74    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() /* empty set */
118        }
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, "{{}}") /* empty set */
259        }
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, "{{}}") /* empty set */
273        }
274    }
275}