Signature
idate(string $format, ?int $timestamp = null): int|falsePurpose
idate() extracts a single piece of a date or time and gives it back as an integer. Where date() builds a formatted string, idate() answers one numeric question: what is the year, the month, the ISO week, the number of days in this month, or whether this is a leap year? Because the result is already an int, you can compare it, add to it or use it as an array index without casting.
Signature
Parameters and defaults
$formatis a string that must hold exactly one format character. Unlikedate(), you cannot combine characters or add separators. Characters in the supported set includeY(four-digit year),y(year, one or two digits),m(month number),d(day of the month),H(24-hour hour),h(12-hour hour),i(minutes),s(seconds),t(days in the month),L(1 for a leap year, otherwise 0),z(day of the year, counting from 0),w(day of the week, 0 for Sunday),N(ISO-8601 weekday, 1 for Monday through 7 for Sunday),W(ISO-8601 week number),o(ISO-8601 year),I(1 when daylight saving time is active),B(Swatch beat),U(Unix timestamp) andZ(time zone offset in seconds).$timestampis an optional Unix timestamp. If you omit it or passnull, PHP uses the current time, astime()would. Passingnullhas been allowed since PHP 8.0.
The parts are interpreted in the default time zone, so the same timestamp can give different hours or days under different zones. Always set the zone explicitly when you need repeatable results.
Return value and failure cases
On success you get an int. On failure you get false. A format character that is not recognised produces a warning and a false result. A format string that is not exactly one character is rejected as an invalid argument. If the default time zone is invalid, the date functions emit an E_WARNING.
The PHP 8.2.0 changelog notes that the N and o format characters were added, so avoid them on older runtimes.
Example 1: reading several parts of one timestamp
Because each call returns one part, you call idate() once per part. The timestamp 1700000000 is 2023-11-14 22:13:20 in UTC.
date_default_timezone_set('UTC');
$ts = 1700000000;
echo json_encode([
'year' => idate('Y', $ts),
'month' => idate('m', $ts),
'day' => idate('d', $ts),
'hour' => idate('H', $ts),
'minute' => idate('i', $ts),
'second' => idate('s', $ts),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";{"year":2023,"month":11,"day":14,"hour":22,"minute":13,"second":20}
Example 2: integers have no leading zeros
The most surprising behaviour is that a result such as 04 cannot exist as an integer. The leading zero is dropped, so the two-digit year of 2004 comes back as 4, and five minutes comes back as 5. When you need fixed-width text, pad it yourself.
date_default_timezone_set('UTC');
$ts = 1072915500; // 2004-01-01 00:05:00 UTC
$year = idate('y', $ts);
$minute = idate('i', $ts);
echo json_encode([
'year' => $year,
'yearPadded' => sprintf('%02d', $year),
'minute' => $minute,
'minutePadded' => sprintf('%02d', $minute),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";{"year":4,"yearPadded":"04","minute":5,"minutePadded":"05"}
Example 3: calendar facts for a date
Characters such as L, t, z, N and W turn idate() into a compact calendar helper. The timestamp below is 2024-02-10 12:00:00 UTC, a Saturday in a leap year.
date_default_timezone_set('UTC');
$ts = 1707566400;
echo json_encode([
'leap' => idate('L', $ts),
'daysInMonth' => idate('t', $ts),
'dayOfYear' => idate('z', $ts),
'isoDow' => idate('N', $ts),
'isoWeek' => idate('W', $ts),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";{"leap":1,"daysInMonth":29,"dayOfYear":40,"isoDow":6,"isoWeek":6}
Notice that z is zero-based, so 10 February is reported as 40, not 41.
Edge cases
- Week and year boundaries: the ISO week number
Wcan belong to a different ISO year than the calendar year. Around the turn of the year, pairWwitho, notY. - Zero-based and one-based values:
zstarts at 0,wstarts at 0 for Sunday, whileNruns from 1 to 7. Mixing them up causes off-by-one bugs. - Time zone dependence:
H,d,I,Zand several other characters depend on the default zone. A timestamp near midnight can land on different days in different zones. - Two-digit years:
yreturns a value from 0 to 99, so you cannot tell from the result alone which century it came from. - No timestamp means now: omitting the second argument makes the result change with the clock. That is fine in production code, but it makes tests unstable.
Common mistakes
- Passing a multi-character format such as
'Y-m-d'.idate()accepts one character, so call it once per part or usedate()for a formatted string. - Expecting zero-padded output. The value is an integer, so pad with
sprintf()orstr_pad()when you display it. - Passing a date string instead of an integer timestamp. Convert strings first, for example with
strtotime(), and check that conversion for failure. - Forgetting to set the time zone, which leads to results that differ between servers.
- Treating the return value as always an
int. The declared type isint|false, so strict code should guard againstfalse.
Related functions
date()formats a timestamp as a string and allows several characters at once.getdate()returns many date parts in a single associative array.DateTimeInterface::format()is the object-oriented equivalent ofdate().time()returns the current Unix timestamp, which is whatidate()uses by default.
Recap
idate() takes exactly one format character and an optional timestamp, and returns that part of the date as an integer, or false on failure. Set the time zone explicitly, remember that leading zeros disappear, and be careful with zero-based parts such as z and w. For anything that needs several parts or formatted text, use date(), getdate() or DateTimeInterface::format().
Tested examples
date_default_timezone_set('UTC');
$ts = 1700000000;
echo json_encode([
'year' => idate('Y', $ts),
'month' => idate('m', $ts),
'day' => idate('d', $ts),
'hour' => idate('H', $ts),
'minute' => idate('i', $ts),
'second' => idate('s', $ts),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
{"year":2023,"month":11,"day":14,"hour":22,"minute":13,"second":20}
date_default_timezone_set('UTC');
$ts = 1072915500; // 2004-01-01 00:05:00 UTC
$year = idate('y', $ts);
$minute = idate('i', $ts);
echo json_encode([
'year' => $year,
'yearPadded' => sprintf('%02d', $year),
'minute' => $minute,
'minutePadded' => sprintf('%02d', $minute),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
{"year":4,"yearPadded":"04","minute":5,"minutePadded":"05"}
date_default_timezone_set('UTC');
$ts = 1707566400;
echo json_encode([
'leap' => idate('L', $ts),
'daysInMonth' => idate('t', $ts),
'dayOfYear' => idate('z', $ts),
'isoDow' => idate('N', $ts),
'isoWeek' => idate('W', $ts),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
{"leap":1,"daysInMonth":29,"dayOfYear":40,"isoDow":6,"isoWeek":6}