Rust LogoCalendar App

A Calendar App is a software application designed to help users organize their schedules, track appointments, set reminders, and manage events effectively. It serves as a digital planner, offering functionalities that range from simply displaying dates to complex event management with notifications and synchronization across multiple devices.

Key features typically include:
* Date Navigation: Allowing users to view days, weeks, months, or years.
* Event Creation: Adding new events with details such as title, description, start and end times, location, and participants.
* Event Management: Editing, deleting, and marking events as complete.
* Reminders and Notifications: Alerting users before an event's start time.
* Recurring Events: Scheduling events that repeat daily, weekly, monthly, or annually.
* Categorization/Tagging: Organizing events by type (e.g., work, personal, holiday).
* Persistence: Storing event data, either in-memory (for temporary use), in local files, or in a database for long-term storage and synchronization.
* User Interface: Can be command-line interface (CLI), graphical user interface (GUI), or web-based.

At its core, a calendar app manages a collection of events, each typically defined by a unique identifier, a title, a description, a start date/time, and an end date/time. Advanced features might include handling time zones, internationalization for various date formats and languages, and integration with other services.

For this example, we will implement a simplified command-line Calendar App in Rust. This app will allow users to add new events and list events for a specific day. Events will be stored in memory and will not persist after the application closes. We will leverage the `chrono` crate for robust date and time handling.

Example Code

// In your Cargo.toml, add:
// [dependencies]
// chrono = "0.4.31"
//
// To run this Rust code:
// 1. Create a new Rust project: `cargo new calendar_app`
// 2. Navigate into the project directory: `cd calendar_app`
// 3. Add the 'chrono' dependency to `Cargo.toml` as shown above.
// 4. Replace the content of `src/main.rs` with the code below.
// 5. Run the application: `cargo run`

use chrono::{Local, NaiveDateTime, DateTime, Datelike};
use std::io::{self, Write}; // For flush

// 1. Define the Event struct
#[derive(Debug, Clone)]
struct Event {
    title: String,
    description: String,
    datetime: DateTime<Local>,
}

impl Event {
    fn new(title: String, description: String, datetime: DateTime<Local>) -> Self {
        Event {
            title,
            description,
            datetime,
        }
    }

    fn display(&self) {
        println!(
            "Title: {}
Description: {}
Date/Time: {}
",
            self.title,
            self.description,
            self.datetime.format("%Y-%m-%d %H:%M").to_string()
        );
    }
}

// 2. Define the Calendar struct to hold events
#[derive(Debug, Default)]
struct Calendar {
    events: Vec<Event>,
}

impl Calendar {
    fn add_event(&mut self, event: Event) {
        self.events.push(event);
        // Keep events sorted by datetime
        self.events.sort_by_key(|e| e.datetime);
        println!("Event added successfully!");
    }

    fn list_events_for_day(&self, year: i32, month: u32, day: u32) {
        let mut found_events = false;
        println!("\n--- Events for {}-{:02}-{:02} ---", year, month, day);
        for event in &self.events {
            if event.datetime.year() == year
                && event.datetime.month() == month
                && event.datetime.day() == day
            {
                event.display();
                found_events = true;
            }
        }
        if !found_events {
            println!("No events found for this day.");
        }
        println!("-------------------------------\n");
    }
}

// Helper function to read a line from stdin with a prompt
fn read_line(prompt: &str) -> String {
    print!("{}", prompt);
    io::stdout().flush().expect("Could not flush stdout"); // Ensure prompt is displayed
    let mut input = String::new();
    io::stdin()
        .read_line(&mut input)
        .expect("Failed to read line");
    input.trim().to_string()
}

// Helper function to parse datetime string into DateTime<Local>
fn parse_datetime(datetime_str: &str) -> Result<DateTime<Local>, String> {
    // Expected format: YYYY-MM-DD HH:MM
    let naive_datetime = NaiveDateTime::parse_from_str(datetime_str, "%Y-%m-%d %H:%M")
        .map_err(|e| format!("Failed to parse datetime: {}", e))?;

    match Local.from_local_datetime(&naive_datetime) {
        chrono::LocalResult::Single(dt) => Ok(dt),
        chrono::LocalResult::Ambiguous(_, _) => Err("Ambiguous datetime (occurs during DST transitions)".to_string()),
        chrono::LocalResult::None => Err("Invalid or non-existent datetime".to_string()),
    }
}

fn main() {
    let mut calendar = Calendar::default();

    loop {
        println!("Calendar App Menu:");
        println!("1. Add Event");
        println!("2. List Events for a Specific Day");
        println!("3. Exit");
        let choice = read_line("Enter your choice: ");

        match choice.as_str() {
            "1" => {
                let title = read_line("Enter event title: ");
                let description = read_line("Enter event description: ");
                let datetime_str = read_line("Enter date and time (YYYY-MM-DD HH:MM): ");

                match parse_datetime(&datetime_str) {
                    Ok(datetime) => {
                        let event = Event::new(title, description, datetime);
                        calendar.add_event(event);
                    }
                    Err(e) => {
                        eprintln!("Error: {}. Please use YYYY-MM-DD HH:MM format.", e);
                    }
                }
            }
            "2" => {
                let date_str = read_line("Enter date to list events for (YYYY-MM-DD): ");
                let parts: Vec<&str> = date_str.split('-').collect();
                if parts.len() == 3 {
                    if let (
                        Ok(year),
                        Ok(month),
                        Ok(day),
                    ) = (
                        parts[0].parse::<i32>(),
                        parts[1].parse::<u32>(),
                        parts[2].parse::<u32>(),
                    ) {
                        calendar.list_events_for_day(year, month, day);
                    } else {
                        eprintln!("Invalid date format. Please use YYYY-MM-DD for year, month, and day.");
                    }
                } else {
                    eprintln!("Invalid date format. Please use YYYY-MM-DD.");
                }
            }
            "3" => {
                println!("Exiting Calendar App. Goodbye!");
                break;
            }
            _ => {
                println!("Invalid choice. Please try again.");
            }
        }
    }
}