How to Get the Number of Days in a Specific Month in Batch Script
Knowing how many days are in a given month is essential for building date validators, calendar generators, and retention calculators. While most months have a fixed day count, February changes between 28 and 29 depending on whether it's a leap year. In Batch, we can use a lookup table combined with a leap year check to determine the correct count.
In this guide, we will demonstrate how to find the day count for any month and year.
The Strategy: Lookup Table + Leap Year Check
- Store the number of days for each month in a variable array.
- For February, check if the given year is a leap year.
- If it is, return 29; otherwise, return 28.
Implementation Script
@echo off
setlocal enabledelayedexpansion
:: 1. Define the Days-per-Month Lookup Table
set "DAYS_1=31" & set "DAYS_2=28" & set "DAYS_3=31"
set "DAYS_4=30" & set "DAYS_5=31" & set "DAYS_6=30"
set "DAYS_7=31" & set "DAYS_8=31" & set "DAYS_9=30"
set "DAYS_10=31" & set "DAYS_11=30" & set "DAYS_12=31"
:: 2. Input
set /p "month=Enter month (1-12): "
set /p "year=Enter year (YYYY): "
:: Remove any leading zeros from month properly
for /f "tokens=* delims=0" %%a in ("!month!") do set "m=%%a"
if "!m!"=="" set "m=0"
:: 3. Validate month range
if !m! LSS 1 (
echo [ERROR] Month must be between 1 and 12.
pause
exit /b
)
if !m! GTR 12 (
echo [ERROR] Month must be between 1 and 12.
pause
exit /b
)
:: Validate year (basic check)
if !year! LSS 1 (
echo [ERROR] Year must be a positive number.
pause
exit /b
)
:: 4. Get the base day count
set "result=!DAYS_%m%!"
:: 5. Leap Year Check (only matters for February)
if !m! EQU 2 (
set /a "mod4=!year! %% 4"
set /a "mod100=!year! %% 100"
set /a "mod400=!year! %% 400"
if !mod4! EQU 0 (
if !mod100! EQU 0 (
if !mod400! EQU 0 (
set "result=29"
) else (
set "result=28"
)
) else (
set "result=29"
)
)
)
echo.
echo ==========================================
echo MONTH: !month! YEAR: !year!
echo DAYS: !result!
echo ==========================================
pause
Each month's day count is stored in a numbered variable (DAYS_1 through DAYS_12). The computed month number m is used to resolve the correct variable via !DAYS_%m%!. This works because %m% is expanded first (providing the index number), and then !DAYS_N! is resolved via delayed expansion to retrieve the stored value.
Why Get the Days in a Month?
- Date Validation: Ensuring that a user-entered date like "February 30" is rejected as invalid.
- Calendar Generation: Building a text-based calendar display requires knowing exactly how many rows each month needs.
- Retention Calculations: If your cleanup script deletes "files older than one month," you need to know whether "one month ago" means 28, 29, 30, or 31 days.
Leap Year Rules
A year is a leap year if:
- It is divisible by 4, AND
- It is NOT divisible by 100, UNLESS
- It is also divisible by 400.
| Year | Leap? | Reason |
|---|---|---|
| 2024 | Yes | Divisible by 4 |
| 1900 | No | Divisible by 100 but not 400 |
| 2000 | Yes | Divisible by 400 |
| 2023 | No | Not divisible by 4 |
Important Considerations
Batch treats numbers with leading zeros as octal. The month values 08 and 09 are invalid octal numbers and cause errors with set /a. The trick set /a "m=1!month:~-2! - 100" takes the last 2 characters of the input, prepends a 1 to create a valid decimal number (e.g., 108), then subtracts 100 to get the correct value (8).
The expression !DAYS_%m%! uses mixed expansion: %m% is resolved first via percent expansion during parsing (providing the numeric index), then !DAYS_N! is resolved via delayed expansion at runtime. This two-phase expansion is a standard Batch pattern for accessing array-like variables by a computed index.
You can wrap this logic into a callable function for use in larger scripts:
call :days_in_month 2 2024 result
echo February 2024 has %result% days
Move the lookup table, validation, and leap year check into a :days_in_month subroutine that accepts month, year, and output variable name as parameters.
Conclusion
Getting the number of days in a specific month is a foundational building block for any date-related logic. By combining a simple lookup table with the leap year algorithm, you create a reliable function that handles all 12 months across any year. This capability is essential for building date validators, calendar tools, and time-based automation scripts that operate with calendar-level precision.