checkdate()
Learn how PHP's checkdate() validates a month, day, and year as a Gregorian date. Covers syntax, parameters, leap-year handling, and examples.
Introduction
The checkdate() function checks whether a month, day, and year together form a valid date in the Gregorian calendar. It is the simplest way in PHP to answer a question like "Is February 29 a real date this year?" without parsing strings or constructing a DateTime object.
This page covers the syntax, parameters, and return value of checkdate(), how it handles leap years and out-of-range values, its year-range limit, and when to reach for the DateTime class instead.
Syntax
checkdate(int $month, int $day, int $year): boolParameters
| Parameter | Description |
|---|---|
$month | The month, as an integer. Valid range: 1–12. |
$day | The day of the month. The valid range depends on the month and year — for example, 30 is valid for April but not for February. |
$year | The year, as an integer. Valid range: 1–32767. |
Return value
checkdate() returns true when the date is valid and false otherwise. The date is considered valid when all of these are true: the month is 1–12, the year is 1–32767, and the day falls within the number of days the given month has in the given year (leap years are taken into account).
Basic example
To check whether February 29, 2024 is a valid date (2024 is a leap year, so it is):
The script stores the month, day, and year in variables, passes them to checkdate(), and prints a message based on the boolean it returns.
Leap years and invalid days
The real value of checkdate() is that it knows how many days each month has — including the leap-year rule for February. The same day number can be valid in one year and invalid in the next:
<?php
var_dump(checkdate(2, 29, 2024)); // bool(true) — 2024 is a leap year
var_dump(checkdate(2, 29, 2023)); // bool(false) — 2023 is not
var_dump(checkdate(4, 31, 2024)); // bool(false) — April has only 30 days
var_dump(checkdate(13, 1, 2024)); // bool(false) — month out of range
var_dump(checkdate(0, 1, 2024)); // bool(false) — month must be >= 1Because checkdate() performs these checks itself, you don't have to hard-code which months have 30 or 31 days.
A practical use: validating form input
A common job for checkdate() is to reject impossible dates submitted from a form before you store them or build a DateTime object:
<?php
function validateDate(int $month, int $day, int $year): string
{
if (!checkdate($month, $day, $year)) {
return "Please enter a real calendar date.";
}
return "Saved $year-$month-$day.";
}
echo validateDate(2, 30, 2024) . "\n"; // Please enter a real calendar date.
echo validateDate(12, 25, 2024) . "\n"; // Saved 2024-12-25.The year-range limit and the DateTime alternative
checkdate() only accepts years in the range 1–32767, which is fine for most applications but unsuitable if you need dates outside it. It also takes three separate integers, so you must split a date string yourself first.
For string input or stricter validation, use PHP's DateTime class. DateTime::createFromFormat() parses a date against a custom format, and combining it with DateTime::getLastErrors() lets you detect values that PHP silently "rolls over" (such as turning February 30 into March 1 or 2):
<?php
$input = '2024-02-30';
$date = DateTime::createFromFormat('Y-m-d', $input);
$errors = DateTime::getLastErrors();
if ($date === false || $errors['warning_count'] > 0 || $errors['error_count'] > 0) {
echo "Invalid date: $input";
} else {
echo "Valid date: " . $date->format('Y-m-d');
}
// Output: Invalid date: 2024-02-30If you only have month, day, and year as integers, checkdate() is the shorter, dependency-free choice.
Related functions
mktime()— build a Unix timestamp from individual date parts.date()— format a timestamp into a human-readable date string.strtotime()— parse an English textual date into a timestamp.- PHP Date and Time — overview of working with dates in PHP.
Conclusion
checkdate() is the quickest way to confirm that a month, day, and year form a real Gregorian date, with leap years handled for you. Keep its 1–32767 year limit in mind, and switch to DateTime::createFromFormat() when you need to validate date strings or work outside that range.