Dates7 min readExamples run on PHP 8.5.10

date_create()

Learn how PHP 8.4 date_create() builds a DateTime object from a string, how the timezone argument works, and how to handle the false it returns on failure.

Signature

date_create(string $datetime = "now", ?DateTimeZone $timezone = null): DateTime|false
Available since PHP 5.2.07.48.08.18.28.38.48.5All versions →

Purpose

date_create() turns a date and time string into a mutable DateTime object. It is the procedural form of new DateTime(...). The key difference is how it reports bad input: the constructor throws an exception, while date_create() quietly returns false. That makes it convenient when you want to test a string with a simple if and skip try/catch.

Signature

Parameters and defaults

  • $datetime is a string that PHP's date parser understands. The default is "now", so calling date_create() with no arguments gives you the current moment. Absolute values such as 2024-03-15 14:30:00 and relative phrases such as +1 month or next monday are both accepted, and they can be combined in one string.
  • $timezone is an optional DateTimeZone object, defaulting to null. When it is null, PHP uses the default timezone, which you can set with date_default_timezone_set(). The argument is not applied when the string already carries its own zone information, such as an offset like +02:00, a zone abbreviation, or an @ Unix timestamp.

The manual refers to the constructor of DateTimeImmutable for the full list of accepted string formats, since the parsing rules are shared.

Return value and failure

On success you get a new DateTime instance. On failure, such as a string the parser cannot understand, you get false. No exception is thrown and no object is created, so any method call on the result without a check would cause an error. Always compare against false before using the value, unless the input is a literal you control.

Example 1: parsing a fixed string

The default timezone is set explicitly, so the output does not depend on the server configuration.

Example
<?php
date_default_timezone_set('UTC');
$date = date_create('2024-03-15 14:30:00');
echo $date->format('Y-m-d H:i:s T'), "\n";
Output
2024-03-15 14:30:00 UTC

Example 2: supplying a timezone

The same wall-clock text means a different instant depending on the zone. Here the string is read as New York local time, which is daylight saving time in July.

Example
<?php
date_default_timezone_set('UTC');
$zone = new DateTimeZone('America/New_York');
$date = date_create('2024-07-04 09:00:00', $zone);
echo json_encode([
    'local' => $date->format('Y-m-d H:i:s T P'),
    'timestamp' => $date->getTimestamp(),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"local":"2024-07-04 09:00:00 EDT -04:00","timestamp":1720098000}

Example 3: relative text and invalid input

A valid string can contain a relative part, and an invalid one produces false.

Example
<?php
date_default_timezone_set('UTC');
$valid = date_create('2024-01-31 +1 month');
$invalid = date_create('not a real date');
echo json_encode([
    'overflow' => $valid->format('Y-m-d'),
    'invalid' => $invalid,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"overflow":"2024-03-02","invalid":false}

Notice that January 31 plus one month does not land on the end of February. PHP adds one to the month number, gets February 31, and rolls the surplus days into March.

Edge cases

  • Overflowing days are not errors. A string such as 2024-02-30 is parsed successfully and becomes March 1 in a leap year. If you need strict calendar validation, check the components with checkdate() or use date_parse() and examine its warnings.
  • Embedded zones win. If the string says 2024-03-15 10:00:00 +02:00, the $timezone argument does not change the result.
  • Timestamps. A string like @1720098000 is read as a Unix timestamp and the resulting object uses the UTC offset +00:00, regardless of the default zone.
  • "now" is not deterministic. Calling the function without arguments depends on the clock, so avoid it in tests that need stable output.
  • Mutability. The returned DateTime changes in place when you call methods such as modify() or setDate(). Two variables holding the same object see the same change.

Common mistakes

  1. Not checking for false. Writing date_create($input)->format(...) on user input fails when the string is invalid. Store the result, test it with === false, then use it.
  2. Relying on the default timezone by accident. Without an explicit zone, the same code can behave differently between environments. Set the zone or pass a DateTimeZone.
  3. Expecting strict validation. The parser is forgiving, so a successful return does not prove the input was a real calendar date in the form you wanted. For a fixed input format, date_create_from_format() is a better fit.
  4. Passing a string as the timezone. The second parameter must be a DateTimeZone object or null, not a name like 'UTC'.
  5. Mutating a shared object. When you need to derive several dates from one base, clone the object or use an immutable variant.
  • date_create_immutable() returns a DateTimeImmutable, so later changes produce new objects.
  • date_create_from_format() parses a string using an explicit format.
  • DateTime::__construct() is the object-oriented equivalent that throws on failure.
  • date_default_timezone_set() controls the fallback zone.
  • date_parse() and checkdate() help with diagnosing and validating input.

Recap

date_create() builds a DateTime from a string and an optional DateTimeZone, and returns false instead of throwing when parsing fails. Set your timezone deliberately, remember that an embedded zone overrides the argument, expect forgiving day rollover, and check for false before calling any method on the result.

Tested examples

Parse a fixed date string in UTC
<?php
date_default_timezone_set('UTC');
$date = date_create('2024-03-15 14:30:00');
echo $date->format('Y-m-d H:i:s T'), "\n";
Output
2024-03-15 14:30:00 UTC
Create a date in a specific timezone
<?php
date_default_timezone_set('UTC');
$zone = new DateTimeZone('America/New_York');
$date = date_create('2024-07-04 09:00:00', $zone);
echo json_encode([
    'local' => $date->format('Y-m-d H:i:s T P'),
    'timestamp' => $date->getTimestamp(),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"local":"2024-07-04 09:00:00 EDT -04:00","timestamp":1720098000}
Relative text and invalid input
<?php
date_default_timezone_set('UTC');
$valid = date_create('2024-01-31 +1 month');
$invalid = date_create('not a real date');
echo json_encode([
    'overflow' => $valid->format('Y-m-d'),
    'invalid' => $invalid,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"overflow":"2024-03-02","invalid":false}