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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#[derive(Debug, Clone, Copy)]
pub struct AmzDate {
year: u32,
month: u32,
day: u32,
hour: u32,
minute: u32,
second: u32,
}
#[allow(missing_copy_implementations)]
#[derive(Debug, thiserror::Error)]
#[error("ParseAmzDateError")]
pub struct ParseAmzDateError {
_priv: (),
}
impl AmzDate {
pub fn from_header_str(header: &str) -> Result<Self, ParseAmzDateError> {
fn parse(input: &str) -> nom::IResult<&str, [&str; 6]> {
use nom::{
bytes::complete::{tag, take},
combinator::{all_consuming, verify},
sequence::tuple,
};
let mut parser = verify(
all_consuming(tuple((
take(4_usize),
take(2_usize),
take(2_usize),
tag("T"),
take(2_usize),
take(2_usize),
take(2_usize),
tag("Z"),
))),
|&ss: &(&str, &str, &str, &str, &str, &str, &str, &str)| {
[ss.0, ss.1, ss.2, ss.4, ss.5, ss.6]
.iter()
.copied()
.all(|s: &str| s.as_bytes().iter().all(u8::is_ascii_digit))
},
);
let (_, (year_str, month_str, day_str, _, hour_str, minute_str, second_str, _)) =
parser(input)?;
Ok((
input,
[
year_str, month_str, day_str, hour_str, minute_str, second_str,
],
))
}
fn to_u32(input: &str) -> Result<u32, ParseAmzDateError> {
match input.parse::<u32>() {
Ok(x) => Ok(x),
Err(_) => Err(ParseAmzDateError { _priv: () }),
}
}
match parse(header) {
Err(_) => Err(ParseAmzDateError { _priv: () }),
Ok((_, [year_str, month_str, day_str, hour_str, minute_str, second_str])) => Ok(Self {
year: to_u32(year_str)?,
month: to_u32(month_str)?,
day: to_u32(day_str)?,
hour: to_u32(hour_str)?,
minute: to_u32(minute_str)?,
second: to_u32(second_str)?,
}),
}
}
#[must_use]
pub fn to_iso8601(&self) -> String {
format!(
"{:04}{:02}{:02}T{:02}{:02}{:02}Z",
self.year, self.month, self.day, self.hour, self.minute, self.second
)
}
#[must_use]
pub fn to_date(&self) -> String {
format!("{:04}{:02}{:02}", self.year, self.month, self.day,)
}
}