elastic_types/date/
format.rs1use chrono::{self, NaiveDate, NaiveDateTime, NaiveTime, Utc};
2use chrono::format::{DelayedFormat, Item};
3use std::ops::Deref;
4use std::marker::PhantomData;
5use std::borrow::Borrow;
6use std::error::Error;
7use std::fmt::{Display, Formatter, Result as FmtResult};
8use std::vec::IntoIter;
9use super::ChronoDateTime;
10
11#[derive(Debug, Clone, PartialEq)]
19pub struct DateValue(ChronoDateTime);
20
21impl DateValue {
22 pub fn now() -> Self {
24 DateValue(Utc::now())
25 }
26
27 pub fn build(year: i32, month: u32, day: u32, hour: u32, minute: u32, second: u32, milli: u32) -> Self {
29 let ndate = NaiveDate::from_ymd(year, month, day);
30 let ntime = NaiveTime::from_hms_milli(hour, minute, second, milli);
31
32 let date = ChronoDateTime::from_utc(NaiveDateTime::new(ndate, ntime), Utc);
33
34 DateValue(date)
35 }
36}
37
38impl<TFormat> From<FormattableDateValue<TFormat>> for DateValue {
39 fn from(date: FormattableDateValue<TFormat>) -> Self {
40 date.0
41 }
42}
43
44impl From<ChronoDateTime> for DateValue {
45 fn from(date: ChronoDateTime) -> Self {
46 DateValue(date)
47 }
48}
49
50impl PartialEq<ChronoDateTime> for DateValue {
51 fn eq(&self, other: &ChronoDateTime) -> bool {
52 PartialEq::eq(&self.0, other)
53 }
54
55 fn ne(&self, other: &ChronoDateTime) -> bool {
56 PartialEq::ne(&self.0, other)
57 }
58}
59
60impl PartialEq<DateValue> for ChronoDateTime {
61 fn eq(&self, other: &DateValue) -> bool {
62 PartialEq::eq(self, &other.0)
63 }
64
65 fn ne(&self, other: &DateValue) -> bool {
66 PartialEq::ne(self, &other.0)
67 }
68}
69
70impl Borrow<ChronoDateTime> for DateValue {
71 fn borrow(&self) -> &ChronoDateTime {
72 &self.0
73 }
74}
75
76impl Deref for DateValue {
77 type Target = ChronoDateTime;
78
79 fn deref(&self) -> &Self::Target {
80 &self.0
81 }
82}
83
84#[derive(Debug, Clone, PartialEq)]
92pub struct FormattableDateValue<TFormat>(DateValue, PhantomData<TFormat>);
93
94impl<TFormat> FormattableDateValue<TFormat>
95where
96 TFormat: DateFormat,
97{
98 pub fn format<'a>(&'a self) -> FormattedDate<'a> {
100 TFormat::format(&self.0)
101 }
102
103 pub fn parse(date: &str) -> Result<Self, ParseError> {
105 let date = TFormat::parse(date)?;
106
107 Ok(FormattableDateValue::from(date))
108 }
109}
110
111impl<TFormat> From<DateValue> for FormattableDateValue<TFormat> {
112 fn from(date: DateValue) -> Self {
113 FormattableDateValue(date.into(), PhantomData)
114 }
115}
116
117impl<TFormat> Borrow<ChronoDateTime> for FormattableDateValue<TFormat> {
118 fn borrow(&self) -> &ChronoDateTime {
119 self.0.borrow()
120 }
121}
122
123impl<TFormat> PartialEq<ChronoDateTime> for FormattableDateValue<TFormat> {
124 fn eq(&self, other: &ChronoDateTime) -> bool {
125 PartialEq::eq(&self.0, other)
126 }
127
128 fn ne(&self, other: &ChronoDateTime) -> bool {
129 PartialEq::ne(&self.0, other)
130 }
131}
132
133impl<TFormat> PartialEq<FormattableDateValue<TFormat>> for ChronoDateTime {
134 fn eq(&self, other: &FormattableDateValue<TFormat>) -> bool {
135 PartialEq::eq(self, &other.0)
136 }
137
138 fn ne(&self, other: &FormattableDateValue<TFormat>) -> bool {
139 PartialEq::ne(self, &other.0)
140 }
141}
142
143pub trait DateFormat
190where
191 Self: Default,
192{
193 fn parse(date: &str) -> Result<DateValue, ParseError>;
195
196 fn format<'a>(date: &'a DateValue) -> FormattedDate<'a>;
198
199 fn name() -> &'static str;
205}
206
207pub struct FormattedDate<'a> {
213 inner: FormattedDateInner<'a>,
214}
215
216enum FormattedDateInner<'a> {
217 Delayed(DelayedFormat<IntoIter<Item<'a>>>),
218 Buffered(String),
219 Number(i64),
220}
221
222impl<'a> Display for FormattedDateInner<'a> {
223 fn fmt(&self, f: &mut Formatter) -> FmtResult {
224 fn fmt_inner<T>(inner: &T, f: &mut Formatter) -> FmtResult
225 where
226 T: Display,
227 {
228 inner.fmt(f)
229 }
230
231 match *self {
232 FormattedDateInner::Delayed(ref inner) => fmt_inner(inner, f),
233 FormattedDateInner::Buffered(ref inner) => fmt_inner(inner, f),
234 FormattedDateInner::Number(ref inner) => fmt_inner(inner, f),
235 }
236 }
237}
238
239impl<'a> Display for FormattedDate<'a> {
240 fn fmt(&self, f: &mut Formatter) -> FmtResult {
241 self.inner.fmt(f)
242 }
243}
244
245impl<'a> From<DelayedFormat<IntoIter<Item<'a>>>> for FormattedDate<'a> {
246 fn from(formatted: DelayedFormat<IntoIter<Item<'a>>>) -> Self {
247 FormattedDate {
248 inner: FormattedDateInner::Delayed(formatted),
249 }
250 }
251}
252
253impl<'a> From<String> for FormattedDate<'a> {
254 fn from(formatted: String) -> Self {
255 FormattedDate {
256 inner: FormattedDateInner::Buffered(formatted),
257 }
258 }
259}
260
261impl<'a> From<i64> for FormattedDate<'a> {
262 fn from(formatted: i64) -> Self {
263 FormattedDate {
264 inner: FormattedDateInner::Number(formatted),
265 }
266 }
267}
268
269#[derive(Debug)]
271pub struct ParseError {
272 kind: ParseErrorKind,
273}
274
275#[derive(Debug)]
276enum ParseErrorKind {
277 Chrono(chrono::ParseError),
278 Other(String),
279}
280
281impl Display for ParseError {
282 fn fmt(&self, f: &mut Formatter) -> FmtResult {
283 match self.kind {
284 ParseErrorKind::Chrono(ref err) => write!(f, "Chrono error: {}", err),
285 ParseErrorKind::Other(ref err) => write!(f, "Error: {}", err),
286 }
287 }
288}
289
290impl Error for ParseError {
291 fn description(&self) -> &str {
292 match self.kind {
293 ParseErrorKind::Chrono(ref err) => err.description(),
294 ParseErrorKind::Other(ref err) => &err[..],
295 }
296 }
297
298 fn cause(&self) -> Option<&Error> {
299 match self.kind {
300 ParseErrorKind::Chrono(ref err) => Some(err),
301 ParseErrorKind::Other(_) => None,
302 }
303 }
304}
305
306impl From<chrono::ParseError> for ParseError {
307 fn from(err: chrono::ParseError) -> ParseError {
308 ParseError {
309 kind: ParseErrorKind::Chrono(err),
310 }
311 }
312}
313
314impl From<String> for ParseError {
315 fn from(err: String) -> ParseError {
316 ParseError {
317 kind: ParseErrorKind::Other(err),
318 }
319 }
320}