1#[allow(clippy::wildcard_imports)]
2use super::*;
3
4pub fn today() -> String {
10 let secs = SystemTime::now()
11 .duration_since(UNIX_EPOCH)
12 .map(|d| d.as_secs())
13 .unwrap_or(0);
14 let days = (secs / 86_400) as i64;
15 let (y, m, d) = civil_from_days(days);
16 format!("{y:04}-{m:02}-{d:02}")
17}
18
19pub fn utc_now_rfc3339() -> String {
25 let secs = SystemTime::now()
26 .duration_since(UNIX_EPOCH)
27 .map(|d| d.as_secs())
28 .unwrap_or(0);
29 let days = (secs / 86_400) as i64;
30 let rem = secs % 86_400;
31 let (y, m, d) = civil_from_days(days);
32 format!(
33 "{y:04}-{m:02}-{d:02}T{:02}:{:02}:{:02}Z",
34 rem / 3600,
35 (rem % 3600) / 60,
36 rem % 60
37 )
38}
39
40pub fn validate_date(s: &str) -> bool {
45 let b = s.as_bytes();
46 if b.len() != 10 || b[4] != b'-' || b[7] != b'-' {
47 return false;
48 }
49 for &c in &b[0..4] {
50 if !c.is_ascii_digit() {
51 return false;
52 }
53 }
54 for &c in &[b[5], b[6], b[8], b[9]] {
55 if !c.is_ascii_digit() {
56 return false;
57 }
58 }
59 let year = u32::from(b[0] - b'0') * 1000
60 + u32::from(b[1] - b'0') * 100
61 + u32::from(b[2] - b'0') * 10
62 + u32::from(b[3] - b'0');
63 let month = u32::from(b[5] - b'0') * 10 + u32::from(b[6] - b'0');
64 let day = u32::from(b[8] - b'0') * 10 + u32::from(b[9] - b'0');
65 if year < 1970 || !(1..=12).contains(&month) {
66 return false;
67 }
68 day >= 1 && day <= days_in_month(year, month)
69}
70
71pub fn validate_issue_dates(start_date: Option<&str>, due_date: Option<&str>) -> Result<()> {
78 if let Some(start) = start_date
79 && validate_date_msg(start).is_err()
80 {
81 return Err(TixError::Config(format!(
82 "start_date {start:?} must be a `YYYY-MM-DD` calendar date"
83 )));
84 }
85 if let Some(due) = due_date {
86 if validate_date_msg(due).is_err() {
87 return Err(TixError::Config(format!(
88 "due_date {due:?} must be a `YYYY-MM-DD` calendar date"
89 )));
90 }
91 if let Some(start) = start_date
92 && !date_lte(start, due)
93 {
94 return Err(TixError::Config(format!(
95 "due_date {due:?} must be `>= start_date` {start:?}"
96 )));
97 }
98 }
99 Ok(())
100}
101
102pub fn date_lte(a: &str, b: &str) -> bool {
108 a <= b
109}