PHP 8.0: New DateTime/DateTimeImmutable::createFromInterface() methods

Version8.0
TypeNew Feature

PHP's DateTime and DateTimeImmutable classes have methods to create one instance from another.

Both DateTime and DateTimeImmutable classes implement DateTimeInterface

DateTimeInterface
  ├── DateTime
  └── DateTimeImmutable

In PHP 8.0, both DateTime and DateTimeImmutable classes get a new method ::createFromInterface. They behave exactly as they would in createFromMutable and createFromImmutable methods, but the new createFromInterface method, as its name suggests, accepts any DateTimeInterface implementation.

  • DateTime::createFromInterface(DateTimeInterface $object): DateTime
  • DateTimeImmutable::createFromInterface(DateTimeInterface $object): DateTimeImmutable

Backwards compatibility impact

This is a rather simple improvement in PHP 8.0, and it wouldn't be too difficult to mimic this functionality with instanceof checks and calling either of the createFrom* methods available in all PHP versions.

Libraries that extend DateTime and DateTimeImmutable can polyfill this functionality with a bit of trait-foo, using a trait that conditionally declares the createFromInterface method if it's not available in PHP version it runs on.

class MyCustomDateTime {
    use DateTimeCreateFromInterfacePolyfill;
    // ...
}

class MyCustomDateTimeImutable {
    use DateTimeImmutableCreateFromInterfacePolyfill;
    // ..
}

In the appropriately named files (for PSR-4 naming and autoloading), it is now possible to declare the two polyfill traits that will only contain the methods in PHP versions prior to 8.0

// path/to/DateTimeCreateFromInterfacePolyfill.php
if (PHP_VERSION_ID < 80000):
trait DateTimeCreateFromInterfacePolyfill {
    public function createFromInterface(\DateTimeInterface $object): \DateTime {
        if ($object instanceof \DateTimeImmutable) {
            return \DateTime::createFromImmutable($object);
        }
        if ($object instanceof \DateTime) {
            return clone $object;
        }
        throw new \InvalidArgumentException('Unexpected type');
    }
}
else:
trait DateTimeCreateFromInterfacePolyfill {}
endif;
// path/to/DateTimeImmutableCreateFromInterfacePolyfill.php
if (PHP_VERSION_ID < 80000):
trait DateTimeImmutableCreateFromInterfacePolyfill {
    public function createFromInterface(\DateTimeInterface $object): \DateTimeImmutable {
        if ($object instanceof \DateTime) {
            return \DateTimeImmutable::createFromMutable($object);
        }
        if ($object instanceof \DateTimeImmutable) {
            return clone $object;
        }
        throw new \InvalidArgumentException('Unexpected type');
    }
}
else:
trait DateTimeImmutableCreateFromInterfacePolyfill {}
endif;

Implementation Obsolete PR (2018)