summaryrefslogtreecommitdiffstats
path: root/headers/src/header_components/date_time.rs
blob: 314f20cffb023e916512208a828f005b083c2193 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use chrono;
use soft_ascii_string::SoftAsciiString;


use internals::encoder::{EncodingWriter, EncodableInHeader};
use internals::error::EncodingError;
use ::HeaderTryFrom;
use ::error::ComponentCreationError;

#[cfg(feature="serde")]
use serde::{Serialize, Deserialize};

/// A DateTime header component wrapping chrono::DateTime<chrono::Utc>
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
pub struct DateTime(
    #[cfg_attr(feature="serde", serde(with = "super::utils::serde::date_time"))]
    chrono::DateTime<chrono::Utc>
);

impl DateTime {

    /// create a new DateTime of the current Time
    pub fn now() -> DateTime {
        DateTime( chrono::Utc::now() )
    }

    /// create a new DateTime from a `chrono::DateTime<TimeZone>` for any `TimeZone`
    pub fn new<TZ: chrono::TimeZone>( date_time: chrono::DateTime<TZ>) -> DateTime {
        DateTime( date_time.with_timezone( &chrono::Utc ) )
    }

    #[doc(hidden)]
    #[cfg(test)]
    pub fn test_time( modif: u32 ) -> Self {
        use chrono::prelude::*;
        Self::new( FixedOffset::east( 3 * 3600 ).ymd( 2013, 8, 6 ).and_hms( 7, 11, modif ) )
    }
}

impl EncodableInHeader for DateTime {

    fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> {
        let time = SoftAsciiString::from_unchecked(self.to_rfc2822());
        handle.write_str( &*time )?;
        Ok( () )
    }

    fn boxed_clone(&self) -> Box<EncodableInHeader> {
        Box::new(self.clone())
    }
}


impl<TZ> HeaderTryFrom<chrono::DateTime<TZ>> for DateTime
    where TZ: chrono::TimeZone
{
    fn try_from(val: chrono::DateTime<TZ>) -> Result<Self, ComponentCreationError> {
        Ok(Self::new(val))
    }
}

impl<TZ> From<chrono::DateTime<TZ>> for DateTime
    where TZ: chrono::TimeZone
{
    fn from(val: chrono::DateTime<TZ>) -> Self {
        Self::new(val)
    }
}

impl Into<chrono::DateTime<chrono::Utc>> for DateTime {
    fn into(self) -> chrono::DateTime<chrono::Utc> {
        self.0
    }
}

deref0!{-mut DateTime => chrono::DateTime<chrono::Utc> }


#[cfg(test)]
mod test {
    use super::DateTime;

    ec_test!{ date_time, {
        DateTime::test_time( 45 )
    } => ascii => [
        Text "Tue,  6 Aug 2013 04:11:45 +0000"
    ]}

}