use chrono::DateTime;
static WEEKS_PER_YEAR: u32 = 52;
pub enum LifeCalendarStyle {
Full,
Short { rows: u32, offset: i32 },
}
pub struct LifeCalendarConfig {
pub style: LifeCalendarStyle,
pub years_total: u32,
pub birth_date: DateTime<chrono::Local>,
}
pub struct LifeCalendar {
style: LifeCalendarStyle,
years_total: u32,
weeks_total: u32,
weeks_lived: u32,
}
impl LifeCalendar {
pub fn from_cfg(config: LifeCalendarConfig) -> Self {
let seconds_lived = chrono::Local::now().timestamp() - config.birth_date.timestamp();
let weeks_lived = (seconds_lived / 60 / 60 / 24 / 7) as u32;
Self {
style: config.style,
years_total: config.years_total,
weeks_total: config.years_total * WEEKS_PER_YEAR,
weeks_lived,
}
}
pub fn print(&self) {
LifeCalendar::print_delimiter();
let years_lived = self.weeks_lived / WEEKS_PER_YEAR;
let (start_year, end_year) = match self.style {
LifeCalendarStyle::Short { rows, offset } => (
(years_lived as i32 + offset) as u32,
(years_lived as i32 + offset) as u32 + rows,
),
LifeCalendarStyle::Full => (0, self.years_total),
};
for i in start_year..end_year {
self.print_row(i);
}
LifeCalendar::print_delimiter();
self.print_stats();
}
fn print_delimiter() {
let delimiter = "═".repeat((WEEKS_PER_YEAR + 12) as usize);
println!("{}", delimiter);
}
fn print_row(&self, year: u32) {
let lived_week_str = "█";
let future_week_str = "░";
let start_week = year * WEEKS_PER_YEAR;
let end_week = start_week + WEEKS_PER_YEAR;
print!(" {:2} - {:2} | ", year, year + 1);
for i in start_week..=end_week {
let week_str = if i <= self.weeks_lived {
lived_week_str
} else {
future_week_str
};
print!("{}", week_str);
}
print!("\n");
}
fn print_stats(&self) {
let life_progress = (self.weeks_lived as f32) / (self.weeks_total as f32) * 100.0;
println!("Your life is {life_progress:.1}% over.");
}
}