QUESTION #030

Date Validator with Leap Year Detection

Easy

๐Ÿ“‹ Problem Statement

Write a program to input a given specific date and check whether the date is valid or not. Year will be in range 1900 to 9999.

๐Ÿ“… Date Validation Rules

  • Year: Must be between 1900 and 9999
  • Month: Must be between 1 and 12
  • Day: Must be valid for the specific month
  • Leap Year February: Special handling for 29th February
Month Day Limits
31 Days: Jan, Mar, May, Jul, Aug, Oct, Dec (7 months)
30 Days: Apr, Jun, Sep, Nov (4 months)
28/29 Days: Feb (depends on leap year) (1 month)

Leap Year Detection:
  โ”Œโ”€ Divisible by 400? โ†’ YES (Leap Year)
  โ”œโ”€ Divisible by 100? โ†’ NO (Not Leap)
  โ”œโ”€ Divisible by 4?   โ†’ YES (Leap Year)
  โ””โ”€ Otherwise         โ†’ NO (Not Leap)

Example: 29/02/1998
         โ†“   โ†“   โ†“
        29  02  1998
         ?   โœ“   โœ“

Is 1998 a leap year?
  รท 400? No
  รท 100? No
  รท 4?   No (1998รท4 = 499.5)
  โ†’ Not a leap year
  โ†’ February has only 28 days
  โ†’ 29th February doesn't exist!
  
Result: Invalid โœ—

๐Ÿ“ฅ Input Format

Accept three integer as a input separated by a '/'

๐Ÿ“ค Output Format

Print the date is "Valid" or "Invalid"

๐Ÿ’ก Examples

Example 1:
Input: 29/02/1998
Output: Invalid
Validation:
โ€ข Day: 29 โ†’ To be checked
โ€ข Month: 02 (February) โ†’ Valid โœ“
โ€ข Year: 1998 โ†’ Valid (1900 โ‰ค 1998 โ‰ค 9999) โœ“
โ€ข Leap Year Check: 1998 is NOT divisible by 4 โ†’ Not a leap year
โ€ข February 1998 has 28 days, not 29
Conclusion: 29th February doesn't exist in 1998
Example 2:
Input: 17/10/1994
Output: Valid
Validation:
โ€ข Day: 17 โ†’ To be checked
โ€ข Month: 10 (October) โ†’ Valid โœ“
โ€ข Year: 1994 โ†’ Valid โœ“
โ€ข October has 31 days
โ€ข 17 โ‰ค 31 โ†’ Valid โœ“
Conclusion: All components are valid
Example 3 (Leap Year):
Input: 29/02/2000
Output: Valid
Validation:
โ€ข Year 2000 is divisible by 400 โ†’ Leap year โœ“
โ€ข February 2000 has 29 days
โ€ข 29th February 2000 exists
Conclusion: Valid leap year date
Example 4 (Century Non-Leap):
Input: 29/02/1900
Output: Invalid
Validation:
โ€ข Year 1900: Divisible by 100 but NOT by 400
โ€ข 1900 is NOT a leap year (special case)
โ€ข February 1900 has only 28 days
Conclusion: Invalid - century year exception
Example 5 (Invalid Month):
Input: 15/13/2023
Output: Invalid
Validation:
โ€ข Month: 13 โ†’ Invalid (13 > 12) โœ—
Conclusion: Month 13 doesn't exist
Example 6 (Invalid Day for Month):
Input: 31/04/2020
Output: Invalid
Validation:
โ€ข Month: 04 (April) โ†’ Valid โœ“
โ€ข April has only 30 days
โ€ข Day: 31 โ†’ Invalid (31 > 30) โœ—
Conclusion: April doesn't have 31 days

โš ๏ธ Constraints

1 <= INPUT <= 9999

โœ… Solution

#include <iostream>
using namespace std;

int main() {
    int day, month, year;
    char slash1, slash2;
    
    cin >> day >> slash1 >> month >> slash2 >> year;
    
    // Check year range
    if (year < 1900 || year > 9999) {
        cout << "Invalid" << endl;
        return 0;
    }
    
    // Check month range
    if (month < 1 || month > 12) {
        cout << "Invalid" << endl;
        return 0;
    }
    
    // Determine maximum days in the month
    int maxDays;
    
    if (month == 2) {  // February
        // Leap year detection
        bool isLeapYear = (year % 400 == 0) || 
                          (year % 4 == 0 && year % 100 != 0);
        
        maxDays = isLeapYear ? 29 : 28;
    } 
    else if (month == 4 || month == 6 || month == 9 || month == 11) {
        // April, June, September, November
        maxDays = 30;
    } 
    else {
        // January, March, May, July, August, October, December
        maxDays = 31;
    }
    
    // Check if day is valid for this month
    if (day >= 1 && day <= maxDays) {
        cout << "Valid" << endl;
    } else {
        cout << "Invalid" << endl;
    }
    
    return 0;
}

๐Ÿ”ฌ Understanding Leap Year Logic

Gregorian Calendar Rules:

// Leap year detection algorithm:

bool isLeapYear = (year % 400 == 0) || 
                  (year % 4 == 0 && year % 100 != 0);

// Breaking it down:

// Condition 1: Divisible by 400
(year % 400 == 0)
// Examples: 1600, 2000, 2400 โ†’ Leap years

// OR

// Condition 2: Divisible by 4 BUT NOT by 100
(year % 4 == 0 && year % 100 != 0)
// Examples: 2004, 2008, 2020 โ†’ Leap years
// But NOT: 1700, 1800, 1900 โ†’ Not leap years

Test Cases for Leap Years:

Year รท400? รท100? รท4? Leap Year? Explanation
2000 โœ… โœ… โœ… YES Divisible by 400
1900 โŒ โœ… โœ… NO Century year not รท400
2004 โŒ โŒ โœ… YES รท4 but not รท100
1998 โŒ โŒ โŒ NO Not divisible by 4
2024 โŒ โŒ โœ… YES รท4 but not รท100

๐Ÿ“† Days in Each Month

Month # Month Name Days Memory Aid
1 January 31 31 days: Jan, Mar, May, Jul, Aug, Oct, Dec
2 February 28/29 Leap year dependent
3 March 31
4 April 30 30 days: Apr, Jun, Sep, Nov
("Thirty days hath...")
5 May 31
6 June 30
7 July 31
8 August 31 Jul & Aug both 31!
9 September 30
10 October 31
11 November 30
12 December 31

Memory Rhyme:

Thirty days hath September,
April, June, and November.
All the rest have thirty-one,
Except for February alone,
Which has twenty-eight days clear,
And twenty-nine in each leap year.

๐Ÿ”„ Validation Flow Diagram

Input: day/month/year
         โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Step 1: Validate Year   โ”‚
โ”‚ Is 1900 โ‰ค year โ‰ค 9999?  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ†“ NO โ†’ Invalid
         โ†“ YES
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Step 2: Validate Month  โ”‚
โ”‚ Is 1 โ‰ค month โ‰ค 12?      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ†“ NO โ†’ Invalid
         โ†“ YES
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Step 3: Determine       โ”‚
โ”‚ Max Days for Month      โ”‚
โ”‚                         โ”‚
โ”‚ โ”Œโ”€ Month == 2?         โ”‚
โ”‚ โ”œโ”€โ”€โ”€ YES โ†’ Leap Year?  โ”‚
โ”‚ โ”‚         โ”œโ”€ YES โ†’ 29  โ”‚
โ”‚ โ”‚         โ””โ”€ NO  โ†’ 28  โ”‚
โ”‚ โ”œโ”€ Month in {4,6,9,11}?โ”‚
โ”‚ โ”‚         โ””โ”€ YES โ†’ 30  โ”‚
โ”‚ โ””โ”€ Else  โ†’ 31          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Step 4: Validate Day    โ”‚
โ”‚ Is 1 โ‰ค day โ‰ค maxDays?   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ†“ NO โ†’ Invalid
         โ†“ YES
       Valid!

โš ๏ธ Common Edge Cases to Test

Edge Case Example Expected Why
Leap year Feb 29 29/02/2000 Valid 2000 รท 400 = leap
Non-leap Feb 29 29/02/1998 Invalid 1998 not leap year
Century non-leap 29/02/1900 Invalid 1900 not รท 400
April 31st 31/04/2023 Invalid April has 30 days
Month 13 15/13/2023 Invalid Only 12 months
Day 0 0/05/2023 Invalid Days start at 1
Year 1899 15/05/1899 Invalid Before 1900
Year 10000 15/05/10000 Invalid After 9999
Dec 31st 31/12/2023 Valid Last day of year
Jan 1st 1900 1/01/1900 Valid First allowed date

๐Ÿ”‘ Key Concepts Learned

  • Complex Validation: Multi-step validation with dependencies
  • Leap Year Algorithm: Understanding Gregorian calendar rules
  • Conditional Logic: Nested if-else for month-based day validation
  • Ternary Operator: Compact leap year to max days conversion
  • Early Return: Exiting function when validation fails
  • Input Parsing: Reading slash-separated date format
  • Logical Operators: Combining conditions with && and ||

๐ŸŒ Real-world Applications

  • Form Validation: Birthdate, appointment date validation in web apps
  • Database Integrity: Ensuring valid dates before insertion
  • Booking Systems: Hotel, flight, event date validation
  • Payroll Systems: Validating work periods and payment dates
  • Age Verification: Calculating valid birthdates for age restrictions
  • Calendar Applications: Preventing invalid event dates
  • Financial Software: Transaction date validation
  • Medical Records: Ensuring valid appointment and prescription dates
  • Travel Systems: Departure/arrival date validation

๐Ÿ’ช Extension Challenges

  • Level 1: Calculate day of week for valid dates (Zeller's algorithm)
  • Level 2: Calculate days between two valid dates
  • Level 3: Add time validation (full datetime validator)
  • Level 4: Support multiple date formats (DD/MM/YYYY, MM/DD/YYYY, YYYY-MM-DD)
  • Level 5: Add next/previous day calculator
  • Level 6: Validate historical dates (handle calendar changes)
  • Level 7: Create age calculator from birthdate
  • Bonus: Build a complete calendar system with holidays

๐Ÿ’ก Practice Tips

  • Test All Edge Cases: Use the edge case table above
  • Understand Leap Years: Practice with years 1900, 2000, 2004, 2100
  • Learn the Rhyme: Memorize "Thirty days hath September..."
  • Trace Validation: Draw flowchart and follow for each test case
  • Test February: Special attention to Feb 28 vs 29
  • Boundary Testing: Try day 0, day 32, month 0, month 13
  • Study Calendars: Look at real calendars to understand patterns
  • Research History: Learn about Gregorian calendar adoption

๐ŸŽ“ Why Date Validation Matters

Date validation is one of the most common validation tasks in programming. Incorrect date handling can lead to:

  • Database corruption (invalid dates stored)
  • Application crashes (arithmetic on invalid dates)
  • Business logic errors (wrong billing periods, expired licenses)
  • Security vulnerabilities (age verification bypass)
  • User frustration (rejected valid inputs, accepted invalid ones)

This problem teaches you to handle one of programming's fundamental challenges correctly!