Skip to main content

time_macros/
utc_datetime.rs

1use std::iter::Peekable;
2
3use proc_macro::{TokenStream, token_stream};
4use time_core::unit::*;
5
6use crate::date::Date;
7use crate::error::Error;
8use crate::time::Time;
9use crate::to_tokens::ToTokenStream;
10use crate::{date, time};
11
12pub(crate) struct UtcDateTime {
13    pub(crate) date: Date,
14    pub(crate) time: Time,
15}
16
17impl UtcDateTime {
18    pub(crate) const fn to_timestamp(&self) -> (i64, u32) {
19        const UNIX_EPOCH_JULIAN_DAY: i64 = 2_440_588;
20
21        let julian_day = {
22            let (year, ordinal) = (self.date.year, self.date.ordinal);
23            let adj_year = year + 999_999;
24            let century = adj_year / 100;
25
26            let days_before_year = (1461 * adj_year as i64 / 4) as i32 - century + century / 4;
27            days_before_year + ordinal as i32 - 363_521_075
28        };
29
30        let days = (julian_day as i64 - UNIX_EPOCH_JULIAN_DAY) * Second::per_t::<i64>(Day);
31        let hours = self.time.hour as i64 * Second::per_t::<i64>(Hour);
32        let minutes = self.time.minute as i64 * Second::per_t::<i64>(Minute);
33        let seconds = self.time.second as i64;
34
35        let nanoseconds = if self.date.year < 1970 {
36            1_000_000_000 - self.time.nanosecond
37        } else {
38            self.time.nanosecond
39        };
40
41        (days + hours + minutes + seconds, nanoseconds)
42    }
43}
44
45pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<UtcDateTime, Error> {
46    let date = date::parse(chars)?;
47    let time = time::parse(chars)?;
48
49    if let Some(token) = chars.peek() {
50        return Err(Error::UnexpectedToken {
51            tree: token.clone(),
52        });
53    }
54
55    Ok(UtcDateTime { date, time })
56}
57
58impl ToTokenStream for UtcDateTime {
59    fn append_to(self, ts: &mut TokenStream) {
60        {
    use proc_macro::*;
    ts.extend([TokenTree::from(Punct::new(':', Spacing::Joint)),
                TokenTree::from(Punct::new(':', Spacing::Alone))]);
    ;
    ts.extend([TokenTree::from(Ident::new(&"time", Span::mixed_site()))]);
    ts.extend([TokenTree::from(Punct::new(':', Spacing::Joint)),
                TokenTree::from(Punct::new(':', Spacing::Alone))]);
    ;
    ts.extend([TokenTree::from(Ident::new(&"UtcDateTime",
                        Span::mixed_site()))]);
    ts.extend([TokenTree::from(Punct::new(':', Spacing::Joint)),
                TokenTree::from(Punct::new(':', Spacing::Alone))]);
    ;
    ts.extend([TokenTree::from(Ident::new(&"new", Span::mixed_site()))]);
    ts.extend([TokenTree::Group(Group::new(Delimiter::Parenthesis,
                        {
                            use proc_macro::*;
                            let mut ts = TokenStream::new();
                            let ts_mut = &mut ts;
                            crate::to_tokens::ToTokenStream::append_to(self.date,
                                ts_mut);
                            ts_mut.extend([TokenTree::from(Punct::new(',',
                                                Spacing::Alone))]);
                            ;
                            crate::to_tokens::ToTokenStream::append_to(self.time,
                                ts_mut);
                            ts_mut.extend([TokenTree::from(Punct::new(',',
                                                Spacing::Alone))]);
                            ;
                            ;
                            ts
                        }))]);
    ;
}quote_append! { ts
61            ::time::UtcDateTime::new(
62                #S(self.date),
63                #S(self.time),
64            )
65        }
66    }
67}