|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #81347 2021-03-34 is correct date for DateTime::createFromFormat()
Submitted: 2021-08-10 14:38 UTC Modified: 2021-08-10 16:05 UTC
From: artyomnsk2012 at gmail dot com Assigned:
Status: Open Package: Date/time related
PHP Version: 8.0.9 OS: Ubuntu
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2021-08-10 14:38 UTC] artyomnsk2012 at gmail dot com
2021-03-34 00:00:00 is correct date for \DateTime::createFromFormat()    

var_dump(  \DateTime::createFromFormat('Y-m-d H:i:s', '2021-03-34 00:00:00') ) shows   

class DateTime#1 (3) {
  public $date =>
  string(26) "2021-04-03 00:00:00.000000"
  public $timezone_type =>
  public $timezone =>
  string(3) "UTC"

Expected behaviour is false or null

Test script:
var_dump(  \DateTime::createFromFormat('Y-m-d H:i:s', '2021-03-34 00:00:00') );


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2021-08-10 14:54 UTC] php-bugs at allenjb dot me dot uk
DateTime(Immutable) will roll-over dates and there's currently no way to disable this. You can detect when this happens using ::getLastErrors(). See

I have a utility method that throws exceptions on errors creating a DateTimeImmutable object (the exception message contains the first error encountered, but there's not usually more than 1 in my experience):

    public static function createImmutableFromFormat(string $format, string $time, \DateTimeZone $timezone = null) : \DateTimeImmutable
        $dt = \DateTimeImmutable::createFromFormat($format, $time, $timezone);

        // DateTime errors/warnings can occur even if the object was successfully created (eg. invalid date)
        $errors = \DateTimeImmutable::getLastErrors();
        if (count($errors['errors'] ?? []) > 0) {
            /** @noinspection LoopWhichDoesNotLoopInspection */
            foreach ($errors['errors'] as $pos => $msg) {
                throw new \InvalidArgumentException($msg . ' @ character ' . $pos);
        if (count($errors['warnings'] ?? []) > 0) {
            /** @noinspection LoopWhichDoesNotLoopInspection */
            foreach ($errors['warnings'] as $pos => $msg) {
                throw new \InvalidArgumentException($msg . ' @ character ' . $pos);

        if (! ($dt instanceof \DateTimeImmutable)) {
            throw new \InvalidArgumentException("Invalid DateTime value specified");

        return $dt;
 [2021-08-10 15:02 UTC]
-Type: Bug +Type: Documentation Problem
 [2021-08-10 15:02 UTC]
Apparently, this roll-over behavior is not documented (besides in
an example[1]); I think we should improve that.

[1] <>
 [2021-08-10 16:05 UTC] artyomnsk2012 at gmail dot com
> DateTime(Immutable) will roll-over dates and there's currently no way to disable this.    

However strtotime() function works OK   

var_dump(strtotime('2021-03-34')) outputs false
 [2021-10-07 01:13 UTC] must at valid dot be
This is not a bug.
On one hand, strtotime() is supposed to parse "about any English textual datetime description into a Unix timestamp". As long as no reasonable Englishperson wants to textually describe a datetime as '2021-03-34', it makes sense that strtotime() returns false whenever its argument looks wrong according to the understanding of the common people. (There is a counterexample "35. Mai" in German literature, but that was long before the Unix epoch, and good old Erich K. actually intended it to look wrong, in order to enable crazy things to happen at this date.)
On the other hand, the creation of a DateTime object from a format is just supposed to work whenever it is possible, so it may well start from a "zero" date and the subsequently add 2021 years, 3 months, and 34 days. When I started to learn Java many years ago, the corresponding object behaved in exactly the same way.
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Thu Oct 28 21:03:36 2021 UTC