Dates7 min readExamples run on PHP 8.5.10

strtotime()

Learn how PHP 8.4 strtotime() turns English date text into Unix timestamps, how base timestamps and time zones affect it, and how to handle failures.

Signature

strtotime(string $datetime, ?int $baseTimestamp = null): int|false

Purpose

strtotime() reads a date/time description written in English and converts it to a Unix timestamp: the number of seconds since 1 January 1970 00:00:00 UTC. It accepts absolute text such as 2024-03-15 12:30:00 and relative text such as +1 week, tomorrow or next Monday. Relative phrases are resolved against a base timestamp, which defaults to the current time.

Signature

Parameters and defaults

  • $datetime: the text to parse. The accepted syntax is described in the manual's Date and Time Formats page, which has many subtle rules.
  • $baseTimestamp: the reference point for relative expressions. It defaults to null, which means the current time. Since PHP 8.0.0 this parameter is explicitly nullable.

Both values are interpreted in the default time zone unless the string names its own zone. In real applications, set the zone deliberately with date_default_timezone_set(). The examples here use UTC so that their output never changes.

Return value and failure

The function returns an integer timestamp on success and false when the text cannot be parsed. Always compare with === false. A successful result is an integer and can never be confused with false, but loose checks are still a habit worth avoiding. An invalid time zone setting additionally raises an E_WARNING.

Example: absolute dates

Absolute strings give a fixed timestamp once the time zone is fixed. A string may also carry its own zone, such as UTC.

Example
<?php
date_default_timezone_set('UTC');
echo strtotime('2024-03-15 12:30:00'), "\n";
echo strtotime('2000-09-10'), "\n";
echo strtotime('1970-01-02 00:00:00 UTC'), "\n";
Output
1710505800
968544000
86400

Example: relative phrases and a base timestamp

Passing a base makes relative parsing reproducible. Notice that some phrases keep the base's time of day, while words like tomorrow and weekday names reset it to midnight. Also notice that +1 month from 31 January overflows past the end of February.

Example
<?php
date_default_timezone_set('UTC');
$base = 1706695200;
$formats = ['+1 day', '+1 month', 'first day of next month', 'tomorrow', 'next Monday'];
$result = [];
foreach ($formats as $text) {
    $result[$text] = date('Y-m-d H:i:s', strtotime($text, $base));
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"+1 day":"2024-02-01 10:00:00","+1 month":"2024-03-02 10:00:00","first day of next month":"2024-02-01 10:00:00","tomorrow":"2024-02-01 00:00:00","next Monday":"2024-02-05 00:00:00"}

Example: failure and missing components

When part of a date is missing, PHP takes that part from the base timestamp. With a base of 31 May 2022, the bare word February becomes 31 February, which overflows into March. Adding an explicit day, or using first day of, avoids the problem. Unparseable text returns false.

Example
<?php
date_default_timezone_set('UTC');
$base = strtotime('2022-05-31 00:00:00');
$inputs = ['Not Good', 'February', '1 February', 'first day of February'];
$out = [];
foreach ($inputs as $text) {
    $ts = strtotime($text, $base);
    $out[$text] = $ts === false ? false : date('Y-m-d', $ts);
}
echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"Not Good":false,"February":"2022-03-03","1 February":"2022-02-01","first day of February":"2022-02-01"}

Edge cases

  • Omitted components are copied from the base, so partial dates can silently produce overflowed results.
  • Two-digit years map 00–69 to 2000–2069 and 70–99 to 1970–1999.
  • Range: timestamps typically span 13 December 1901 20:45:54 UTC to 19 January 2038 03:14:07 UTC, the limits of a 32-bit signed integer. On 64-bit PHP the usable range is effectively unlimited.
  • No zone information: the returned integer carries no time zone. Formatting it later with a different default zone shows different local times.
  • Without a base, results depend on the current clock, so they are not reproducible in tests.

Common mistakes

  1. Not checking for false. Passing a failed result to date() would silently format timestamp 0 or raise a type error, depending on the code path. Check first.
  2. Relying on the default time zone. Servers and users differ. Set the zone explicitly or put an offset in the string.
  3. Using it for date arithmetic. The manual advises against doing calculations this way. DateTimeImmutable with add() and sub() is clearer and more capable.
  4. Parsing user input with ambiguous formats. When you know the exact format, DateTimeImmutable::createFromFormat() is stricter.
  5. Month-end surprises. Phrases like +1 month on the 31st overflow. Use first day of or last day of when you mean calendar months.
  • DateTimeImmutable for time zone aware calculations
  • DateTimeImmutable::createFromFormat() for parsing a known format
  • checkdate() for validating a Gregorian date
  • date() for formatting a timestamp
  • strptime() for parsing a time generated by strftime

Recap

strtotime() converts English date text into an integer timestamp or returns false. Relative expressions depend on the base timestamp, and missing parts are inherited from it. Fix the time zone, check with === false, and prefer DateTimeImmutable for real date arithmetic.

Tested examples

Absolute dates in UTC
<?php
date_default_timezone_set('UTC');
echo strtotime('2024-03-15 12:30:00'), "\n";
echo strtotime('2000-09-10'), "\n";
echo strtotime('1970-01-02 00:00:00 UTC'), "\n";
Output
1710505800
968544000
86400
Relative phrases with a base timestamp
<?php
date_default_timezone_set('UTC');
$base = 1706695200;
$formats = ['+1 day', '+1 month', 'first day of next month', 'tomorrow', 'next Monday'];
$result = [];
foreach ($formats as $text) {
    $result[$text] = date('Y-m-d H:i:s', strtotime($text, $base));
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"+1 day":"2024-02-01 10:00:00","+1 month":"2024-03-02 10:00:00","first day of next month":"2024-02-01 10:00:00","tomorrow":"2024-02-01 00:00:00","next Monday":"2024-02-05 00:00:00"}
Failure and missing components
<?php
date_default_timezone_set('UTC');
$base = strtotime('2022-05-31 00:00:00');
$inputs = ['Not Good', 'February', '1 February', 'first day of February'];
$out = [];
foreach ($inputs as $text) {
    $ts = strtotime($text, $base);
    $out[$text] = $ts === false ? false : date('Y-m-d', $ts);
}
echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"Not Good":false,"February":"2022-03-03","1 February":"2022-02-01","first day of February":"2022-02-01"}