parth10606_first_crate 0.1.1

A test lib for publishing
Documentation
/// Checks if a given date string is in valid `YYYY-MM-DD` format
/// 
/// # Arguments
/// 
/// * `date` - String slice that holds date to validate.
/// # Returns
/// 
/// * `Ok(true)` if the date is in valid format and represents a valid calender date
/// * `Ok(false)` if the date is in incorrect format or not a valid calender data
/// * `Err(&str)` is not used in current logic but reserved for future error differentiation.
/// 
/// # Examples
/// 
/// 
/// ```
/// use parth10606_first_crate::utils::date;
/// 
/// assert_eq!(date::format::is_valid_date_format("2025-07-20"),Ok(true));
/// assert_eq!(date::format::is_valid_date_format("2020-02-29"), Ok(true)); // Leap year
/// assert_eq!(date::format::is_valid_date_format("2021-02-29"), Ok(false)); // Not a leap year
/// assert_eq!(date::format::is_valid_date_format("2025-13-01"), Ok(false)); // Invalid month
/// assert_eq!(date::format::is_valid_date_format("abcd-ef-gh"), Ok(false)); // Non-numeric 
/// 
/// ```

pub fn is_valid_date_format(date:&str)->Result<bool,&str>{
    if date.len() != 10{
        return Ok(false);
    }
    // splitting string into 3 parts
    let parts : Vec<&str> = date.split("-").collect();
    if parts.len()!=3{
        return Ok(false);
    }

    // parsing the split parts into numeric values
    let year = parts[0].parse::<i32>();
    let month = parts[1].parse::<u32>();
    let day = parts[2].parse::<u32>();

    // checking for parsing error
    if year.is_err() || month.is_err() || day.is_err() {
        return Ok(false);
    }

    // unwraping values
    let (year,month,day) = (year.unwrap(),month.unwrap(),day.unwrap());

    // checking month condition
    if month == 0 || month > 12{
        return Ok(false);
    }

    // maximum days in a month
    let max_days = match month {
        1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
        4 | 6 | 9 | 11 => 30,
        2 => {
            if (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)  {
                29
            } else {
                28
            }
        }
        _ => return Ok(false), // should never happen
    };

    // validating day
    if day == 0 || day > max_days {
        return Ok(false);
    }

    return Ok(true);

}



#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_dates() {
        let valid_dates = vec![
            "2025-07-20", // Normal date
            "2000-02-29", // Leap year
            "2024-02-29", // Leap year
            "1999-12-31", // End of year
        ];

        for date in valid_dates {
            assert_eq!(is_valid_date_format(date), Ok(true), "Failed for date: {}", date);
        }
    }

    #[test]
    fn test_invalid_format() {
        let invalid_formats = vec![
            "2025/07/20",
            "07-20-2025",
            "2025-7-2",
            "20-2025-07",
            "2025-0720",
            "20250720",
            "",
            "----",
        ];

        for date in invalid_formats {
            assert_eq!(is_valid_date_format(date), Ok(false), "Incorrectly passed format check: {}", date);
        }
    }

    #[test]
    fn test_non_numeric_parts() {
        let bad_inputs = vec![
            "20xx-07-10",
            "2025-aa-01",
            "2025-07-xx",
            "abcd-ef-gh",
        ];

        for date in bad_inputs {
            assert_eq!(is_valid_date_format(date), Ok(false), "Incorrectly passed non-numeric check: {}", date);
        }
    }

    #[test]
    fn test_invalid_months() {
        let invalid_months = vec![
            "2025-00-10",
            "2025-13-10",
        ];

        for date in invalid_months {
            assert_eq!(is_valid_date_format(date), Ok(false), "Incorrectly passed month check: {}", date);
        }
    }

    #[test]
    fn test_invalid_days() {
        let invalid_days = vec![
            "2025-01-00",
            "2025-01-32",
            "2025-04-31", // April has only 30 days
            "2025-02-29", // Not a leap year
            "1900-02-29", // Not a leap year (divisible by 100 but not 400)
        ];

        for date in invalid_days {
            assert_eq!(is_valid_date_format(date), Ok(false), "Incorrectly passed day check: {}", date);
        }
    }
}