Removing microseconds from a PHP DateTime object

Published on 2021-01-23 • Modified on 2021-01-23

In this snippet, we will see how to remove microseconds from a PHP DateTime object. This was a breaking change from PHP 7.0 to 7.1: when creating a new \DateTime object, it now includes microseconds it wasn't the case for PHP 7.0. With immutable objects, use $now = $this->removeAboveSeconds($now);. Note that we have a concrete use case for the new PHP 8 union types. In the removeAboveSeconds() function, with PHP 8 one can type the \DateTime|\DateTimeImmutable $dateTime parameter, remove the related annotation and delete the instanceof test, a nice simplification! If you just want to have the current day without time information you can use new \DateTime('today').


<?php

declare(strict_types=1);

namespace App\Controller\Snippet;

/**
 * I am using a PHP trait to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor.
 */
trait Snippet131Trait
{
    public function snippet131(): void
    {
        $now = new \DateTime();
        var_dump($now);

        $this->removeAboveSeconds($now);
        var_dump($now);

        $today = new \DateTime('today');
        var_dump($today);

        echo 'OK'; // That's it! 😁
    }

    /**
     * The instance check is because setTime() isn't in the DateTime interface.
     */
    public function removeAboveSeconds(\DateTimeInterface $dateTime): \DateTimeInterface
    {
        if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeImmutable) {
            throw new \InvalidArgumentException('Invalid date object.');
        }

        return $dateTime->setTime(
            (int) $dateTime->format('G'), // hours
            (int) $dateTime->format('i'), // minutes
            (int) $dateTime->format('s')  // seconds
        );
    }
}

 Run this snippet  ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  More on Stackoverflow   Read the doc  More on the web

<?php

declare(strict_types=1);

namespace App\Tests\Controller\Snippets;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @covers Snippet131Trait
 */
final class Snippet131Test extends KernelTestCase
{
    /**
     * @covers Snippet131Trait::snippet131
     */
    public function testSnippet131(): void
    {
        $now = new \DateTime();
        $this->removeAboveSeconds($now);

        self::assertSame(0, (int) $now->format('u'));
        self::assertSame(0, (int) $now->format('v'));

        $now = new \DateTime('today');
        self::assertSame(0, (int) $now->format('G'));
        self::assertSame(0, (int) $now->format('i'));
        self::assertSame(0, (int) $now->format('u'));
        self::assertSame(0, (int) $now->format('v'));
    }

    public function removeAboveSeconds(\DateTime $dateTime): \DateTimeInterface
    {
        return $dateTime->setTime(
            (int) $dateTime->format('G'), // hours
            (int) $dateTime->format('i'), // minutes
            (int) $dateTime->format('s')  // seconds
        );
    }
}