time_macros/
datetime.rs

1use std::iter::Peekable;
2
3use proc_macro::{token_stream, Ident, Span, TokenTree};
4
5use crate::date::Date;
6use crate::error::Error;
7use crate::offset::Offset;
8use crate::time::Time;
9use crate::to_tokens::ToTokenTree;
10use crate::{date, offset, time};
11
12pub(crate) struct DateTime {
13    date: Date,
14    time: Time,
15    offset: Option<Offset>,
16}
17
18pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<DateTime, Error> {
19    let date = date::parse(chars)?;
20    let time = time::parse(chars)?;
21    let offset = match offset::parse(chars) {
22        Ok(offset) => Some(offset),
23        Err(Error::UnexpectedEndOfInput | Error::MissingComponent { name: "sign", .. }) => None,
24        Err(err) => return Err(err),
25    };
26
27    if let Some(token) = chars.peek() {
28        return Err(Error::UnexpectedToken {
29            tree: token.clone(),
30        });
31    }
32
33    Ok(DateTime { date, time, offset })
34}
35
36impl ToTokenTree for DateTime {
37    fn into_token_tree(self) -> TokenTree {
38        let (type_name, maybe_offset) = match self.offset {
39            Some(offset) => (
40                Ident::new("OffsetDateTime", Span::mixed_site()),
41                quote!(.assume_offset(#(offset))),
42            ),
43            None => (
44                Ident::new("PrimitiveDateTime", Span::mixed_site()),
45                quote!(),
46            ),
47        };
48
49        quote_group! {{
50            const DATE_TIME: ::time::#(type_name) = ::time::PrimitiveDateTime::new(
51                #(self.date),
52                #(self.time),
53            ) #S(maybe_offset);
54            DATE_TIME
55        }}
56    }
57}