1 | use crate::error::{Error, Result}; |
2 | use crate::iter::Iter; |
3 | use crate::{time, token}; |
4 | use proc_macro::Group; |
5 | use std::fmt::{self, Display}; |
6 | |
7 | #[derive (Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
8 | pub struct Date { |
9 | pub year: u16, |
10 | pub month: u8, |
11 | pub day: u8, |
12 | } |
13 | |
14 | impl Display for Date { |
15 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
16 | write!( |
17 | formatter, |
18 | " {:04}- {:02}- {:02}" , |
19 | self.year, self.month, self.day, |
20 | ) |
21 | } |
22 | } |
23 | |
24 | pub fn parse(paren: Group, iter: Iter) -> Result<Date> { |
25 | try_parse(iter).map_err(|_| { |
26 | let msg: String = format!("expected nightly date, like {}" , time::today()); |
27 | Error::group(group:paren, msg) |
28 | }) |
29 | } |
30 | |
31 | fn try_parse(iter: Iter) -> Result<Date, ()> { |
32 | let year: Literal = token::parse_literal(iter).map_err(op:drop)?; |
33 | token::parse_punct(iter, '-' ).map_err(op:drop)?; |
34 | let month: Literal = token::parse_literal(iter).map_err(op:drop)?; |
35 | token::parse_punct(iter, '-' ).map_err(op:drop)?; |
36 | let day: Literal = token::parse_literal(iter).map_err(op:drop)?; |
37 | |
38 | let year: u64 = year.to_string().parse::<u64>().map_err(op:drop)?; |
39 | let month: u64 = month.to_string().parse::<u64>().map_err(op:drop)?; |
40 | let day: u64 = day.to_string().parse::<u64>().map_err(op:drop)?; |
41 | if year >= 3000 || month > 12 || day > 31 { |
42 | return Err(()); |
43 | } |
44 | |
45 | Ok(Date { |
46 | year: year as u16, |
47 | month: month as u8, |
48 | day: day as u8, |
49 | }) |
50 | } |
51 | |