Dates & Times
Almost every real application eventually has to answer "what time is it?" or "how many days until X?" PHP's oldest answer to that question is a set of procedural functions built around the Unix timestamp — the number of seconds elapsed since midnight UTC on January 1st, 1970. Before reaching for the more powerful DateTime classes, it's worth understanding this procedural layer, because timestamps still show up everywhere: database columns, API payloads, file metadata, and cache expiry logic.
time() and the Unix timestamp
time() takes no arguments and returns the current Unix timestamp as a plain integer. Because it's just a number, timestamps are easy to store, compare, and do arithmetic on — subtracting one timestamp from another gives you a duration in seconds with no extra work.
Getting the current timestamp
<?php $now = time(); echo $now, "\n"; $later = $now + 3600; // one hour from now, in seconds echo $later, "\n";
1735689600 1735693200
Those raw integers aren't very readable, which is where date() comes in — it converts a timestamp into a formatted string using a set of single-letter format characters.
date(): formatting a timestamp
date(string $format, ?int $timestamp = null) accepts a format string built out of special characters, each standing for a piece of the date or time. If you omit the timestamp argument, date() uses the current time, equivalent to calling time() yourself.
Common date() formats
<?php
$timestamp = 1735689600;
echo date('Y-m-d', $timestamp), "\n";
echo date('Y-m-d H:i:s', $timestamp), "\n";
echo date('D, d M Y', $timestamp), "\n";
echo date('l jS \of F Y', $timestamp), "\n";2025-01-01 2025-01-01 00:00:00 Wed, 01 Jan 2025 Wednesday 1st of January 2025
Notice the backslash before "of" in the last line — any character in the format string that isn't a recognized format letter is printed literally, but letters that happen to also be format characters (like the "f" hiding inside a word) need to be escaped with a backslash so date() doesn't try to interpret them.
A quick reference for format characters
Character | Meaning | Example |
|---|---|---|
Y | Four-digit year | 2025 |
y | Two-digit year | 25 |
m | Month, zero-padded | 01 |
n | Month, no padding | 1 |
d | Day of month, zero-padded | 05 |
j | Day of month, no padding | 5 |
H | 24-hour, zero-padded | 09 |
G | 24-hour, no padding | 9 |
i | Minutes, zero-padded | 07 |
s | Seconds, zero-padded | 03 |
D | Short weekday name | Wed |
l | Full weekday name | Wednesday |
M | Short month name | Jan |
F | Full month name | January |
strtotime(): parsing human-readable strings
strtotime() goes the other direction — it takes a string written in a loosely English, human-friendly format and tries to parse it into a Unix timestamp. It's surprisingly capable with relative phrases, which makes it convenient for quick scripts, though its forgiving nature is also a source of subtle bugs.
Parsing relative and absolute dates
<?php
echo date('Y-m-d', strtotime('2025-03-15')), "\n";
echo date('Y-m-d', strtotime('next Monday')), "\n";
echo date('Y-m-d', strtotime('+2 weeks')), "\n";
echo date('Y-m-d', strtotime('first day of next month')), "\n";
$result = strtotime('not a real date');
var_dump($result);2025-03-15 2025-03-17 2025-03-29 2025-04-01 bool(false)
When strtotime() can't make sense of the input, it returns false rather than throwing an error, so any code that feeds user-supplied strings into it should explicitly check the return value before passing it along to date() — formatting false as a timestamp silently coerces it to 0, which is January 1st, 1970, not an error you'll notice right away.
checkdate(): validating a calendar date
Before trusting user input as a real calendar date, checkdate(int $month, int $day, int $year) verifies that the combination actually exists — catching things like February 30th or a day count that ignores leap years.
Validating month, day, and year
<?php var_dump(checkdate(2, 29, 2024)); // 2024 is a leap year var_dump(checkdate(2, 29, 2023)); // 2023 is not var_dump(checkdate(13, 1, 2025)); // month 13 doesn't exist
bool(true) bool(false) bool(false)
Why procedural functions eventually fall short
date(), time(), and strtotime() cover a lot of ground, but they all revolve around plain integers and strings with no object to hold onto. That becomes awkward once a program needs to carry a "date" around as a value — pass it into functions, compare two dates for equality, or perform a chain of calculations like "add three months, then subtract five days, then find the difference from another date." Doing that with raw timestamps means constantly converting back and forth between strings and integers and re-deriving components like "day of week" by hand. PHP's DateTime and DateTimeImmutable classes exist specifically to give dates a proper object representation with methods for exactly this kind of arithmetic and comparison.
time()returns the current Unix timestamp as a plain integer.date($format, $timestamp)turns a timestamp into a formatted string using single-letter format codes.strtotime($string)parses a human-readable string into a timestamp, returningfalseon failure.checkdate($month, $day, $year)checks whether a month/day/year combination is a real calendar date.Raw timestamp arithmetic works for seconds and days but gets unreliable for months, years, and DST-aware calculations.