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
use chrono::prelude::*;
use std::fmt::{self, Display};
const CHARACTERS: &'static str = "abcdefghijklmnopqrstuvwxyz";
const BASE: u32 = CHARACTERS.len() as u32;
pub fn encode(value: u32) -> String {
let mut retval = Vec::<String>::new();
let mut rest = value;
while rest > 0 {
let digit: usize = (rest % BASE) as usize;
rest = rest / BASE;
retval.push(format!("{}", CHARACTERS.get(digit - 1..digit).unwrap()));
}
retval.join("")
}
#[derive(Debug)]
pub struct BatDate {
year: i32,
day: u32,
cycle_count: u32,
segment: u32,
week_day: Weekday,
}
impl Display for BatDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}{}{}.{}",
encode(self.year as u32).to_uppercase(),
encode(self.cycle_count),
self.segment + 1,
self.week_day.num_days_from_monday() + 1
)
}
}
impl From<Date<Local>> for BatDate {
fn from(d: Date<Local>) -> BatDate {
BatDate {
year: d.year(),
day: d.day0(),
week_day: d.weekday(),
cycle_count: d.iso_week().week() / 2,
segment: d.iso_week().week() % 2,
}
}
}
impl From<NaiveDate> for BatDate {
fn from(d: NaiveDate) -> BatDate {
BatDate {
year: d.year(),
day: d.day0(),
week_day: d.weekday(),
cycle_count: d.iso_week().week() / 2,
segment: d.iso_week().week() % 2,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_valid_date() {
let date : BatDate = NaiveDate::parse_from_str("20200517", "%Y%m%d").unwrap().into();
assert_eq!(date.to_string(), "RYBj1.7".to_owned());
}
}