pub mod options;
extern crate chrono;
extern crate rand;
use chrono::naive::*;
use chrono::*;
use rand::Rng;
pub fn week_end_date(now: chrono::DateTime<Local>) -> chrono::DateTime<Local> {
let naive_now = now.naive_local();
let delta_days = match naive_now.date().weekday() {
Weekday::Sat => 0,
Weekday::Sun => 1,
Weekday::Mon => 2,
Weekday::Tue => 3,
Weekday::Wed => 4,
Weekday::Thu => 5,
Weekday::Fri => 6,
};
let naive_d0 = NaiveDateTime::from_timestamp(naive_now.timestamp() - delta_days * 3600 * 24, 0)
.date()
.and_time(NaiveTime::from_hms(0, 0, 0));
let mut delta = naive_now - naive_d0;
delta = delta / 5;
delta = delta
+ if delta < Duration::hours(15) {
Duration::hours(7)
} else {
Duration::hours(14)
};
let new_now = naive_d0 + delta;
let new_date = new_now.date();
let new_time = new_now.time();
offset::Local
.from_local_date(&new_date)
.and_time(new_time)
.unwrap()
}
pub fn random_year_date(year: Option<i32>) -> chrono::DateTime<Local> {
let mut rng = rand::thread_rng();
let y = year.unwrap_or(offset::Local::now().year());
let o = rng.gen_range(0, 365 as u32);
let h = rng.gen_range(0, 24 as u32);
let m = rng.gen_range(0, 60 as u32);
let s = rng.gen_range(0, 60 as u32);
let date = NaiveDate::from_yo(y, o);
let time = NaiveTime::from_hms(h, m, s);
offset::Local.from_local_date(&date).and_time(time).unwrap()
}
pub fn generate(cfg: &options::Config) -> String {
let d = match cfg.week_end {
true => week_end_date(offset::Local::now()),
false => random_year_date(cfg.year),
};
d.to_rfc2822()
}
pub fn run(cfg: &options::Config) {
let txt = generate(cfg);
if cfg.newline {
println!("{}", txt)
} else {
print!("{}", txt)
}
}
#[cfg(test)]
mod tests {
use crate::*;
use std::collections::HashMap;
#[test]
fn test_random_year_date() {
assert_eq!(2020, random_year_date(Some(2020)).year());
assert_eq!(offset::Local::now().year(), random_year_date(None).year());
}
#[test]
fn test_week_end_date() {
struct TestDate {
week_num: u32,
week_day: Weekday,
h: u32,
m: u32,
s: u32,
};
struct TestCase {
input: TestDate,
expected_output: TestDate,
}
let mut test_cases: HashMap<&str, TestCase> = HashMap::new();
test_cases.insert(
"a basic saturday",
TestCase {
input: {
TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 10,
m: 10,
s: 10,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 9,
m: 2,
s: 2,
},
},
);
test_cases.insert(
"an early saturday",
TestCase {
input: {
TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 2,
m: 3,
s: 4,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 7,
m: 24,
s: 36,
},
},
);
test_cases.insert(
"a late saturday",
TestCase {
input: {
TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 22,
m: 30,
s: 0,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 11,
m: 30,
s: 00,
},
},
);
test_cases.insert(
"a sunday noon",
TestCase {
input: {
TestDate {
week_num: 5,
week_day: Weekday::Sun,
h: 12,
m: 0,
s: 0,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 14,
m: 12,
s: 00,
},
},
);
test_cases.insert(
"a monday noon",
TestCase {
input: {
TestDate {
week_num: 6,
week_day: Weekday::Mon,
h: 12,
m: 0,
s: 0,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sat,
h: 19,
m: 00,
s: 00,
},
},
);
test_cases.insert(
"a tuesday aft",
TestCase {
input: {
TestDate {
week_num: 6,
week_day: Weekday::Tue,
h: 16,
m: 30,
s: 5,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sun,
h: 7,
m: 42,
s: 1,
},
},
);
test_cases.insert(
"a wed morning",
TestCase {
input: {
TestDate {
week_num: 6,
week_day: Weekday::Wed,
h: 9,
m: 17,
s: 45,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sun,
h: 11,
m: 3,
s: 33,
},
},
);
test_cases.insert(
"a thu morning",
TestCase {
input: {
TestDate {
week_num: 6,
week_day: Weekday::Thu,
h: 9,
m: 17,
s: 45,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sun,
h: 15,
m: 51,
s: 33,
},
},
);
test_cases.insert(
"a fri evening",
TestCase {
input: {
TestDate {
week_num: 6,
week_day: Weekday::Fri,
h: 23,
m: 55,
s: 15,
}
},
expected_output: TestDate {
week_num: 5,
week_day: Weekday::Sun,
h: 23,
m: 35,
s: 3,
},
},
);
for (key, test_case) in test_cases.into_iter() {
let input_date = offset::Local
.from_local_date(&NaiveDate::from_isoywd(
2020,
test_case.input.week_num,
test_case.input.week_day,
))
.unwrap()
.and_hms(test_case.input.h, test_case.input.m, test_case.input.s);
let expected_output_date = offset::Local
.from_local_date(&NaiveDate::from_isoywd(
2020,
test_case.expected_output.week_num,
test_case.expected_output.week_day,
))
.unwrap()
.and_hms(
test_case.expected_output.h,
test_case.expected_output.m,
test_case.expected_output.s,
);
let output_date = week_end_date(input_date);
assert_eq!(
format!("{}: {}", key, expected_output_date.to_rfc2822()),
format!("{}: {}", key, output_date.to_rfc2822())
);
}
}
}