Sergey Onishchenko
Sergey Onishchenko

Reputation: 7851

php DateTime with date without hours

new \DateTime();
/*
DateTime Object
(
    [date] => 2016-04-20 04:45:24.000000
    [timezone_type] => 3
    [timezone] => UTC
)
*/  

How do I trim hours to get my DateTime object like this:

/*
DateTime Object
(
    [date] => 2016-04-20 00:00:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)
*/

The only way that I know is:

$date = new \DateTime();
$date->format('Y-m-d');
$date = new \DateTime($date->format('Y-m-d'));

But I don't like this solution.

Upvotes: 24

Views: 32043

Answers (6)

Ben
Ben

Reputation: 4867

In case it helps anybody, I've used the following...

new DateTime("00:00");

...this has the advantage of being as short as possible, plus being easy to read. You can also just use...

new DateTime("0:0");

...but it's less easy to read. As above, if you have an object already already, just use...

$object->setTime(0,0)

Upvotes: 0

Luigi C.
Luigi C.

Reputation: 1060

A very clean solution is to create a Value Object called Date that wraps a \DateTime and set the time part to zero. Here an example:

class Date
{
    private DateTimeImmutable $dateTime;

    public function __construct(DateTimeInterface $dateTime)
    {
        $this->dateTime = DateTimeImmutable::createFromInterface($dateTime)->setTime(0, 0);
    }

    public function format($format = ''): string
    {
        return $this->dateTime->format($format);
    }
}

You can also customize the format method to only use the 'Y-m-d' format.

Using a Value Object is much more expressive since reading the code you always know if your variable is just a date or a date with time.

Upvotes: 2

Cláudio Silva
Cláudio Silva

Reputation: 915

For those of you who love doing stuff in the shortest possible way, here are one-liners for getting the current date or parsing a string date into a DateTime object and simultaneously set hours, minutes and seconds to 0.

For today's date:

$dateObj = new DateTime ("today");

For a specific date:

$dateObj = new DateTime ("2019-02-12"); //time part will be 0

For parsing a specific date format:

$dateObj = DateTime::createFromFormat ('!Y-m-d', '2019-02-12'); //notice the !

Upvotes: 12

paul.ago
paul.ago

Reputation: 4103

Sadly PHP doesn't have a native class for dealing with dates without time. Since Doctrine and a lot of other libraries work with DateTime anyway, the best approach I've found is just using a helper class to create DateTime objects with time set to 0.

class DateFactory
{
    public static function createOnlyDateFromFormat(string $format, string $value): \DateTime
    {
        $date = \DateTime::createFromFormat($format, $value);
        $date->setTime(0, 0, 0);

        return $date;
    }
}

Upvotes: 0

bortunac
bortunac

Reputation: 4808

extend DateTime for comfort

 class DT extends \DateTime {

  static function __diff($dt1, $dt2 = NULL){
    $a = gettype($dt1) === "string" ? new DateTime($dt1) :$dt1;
    $b = gettype($dt2) === "string" ? new DateTime($dt2) :$dt2 ?? new DateTime();
    return $a->diff($b);
    }

  public function __get($name) { // sql format
    switch ($name) {
        case "date":
            return $this->format("Y-m-d");
        case "time":
            return $this->format("H:i:s");
        case "datetime":
            return $this->date." ".$this->time;
        default:
            return $this->$name;
      }
  }

  public function days2($date){
    $to = gettype($date) === "string" ? new \DateTime($date):$date;
    return (int)$this->__diff($this->date,$to)->format('%R%a'); 
  }
}

so

$d=new DT(); echo $d->date; echo $d->days2('2018-10-21')

Upvotes: 0

splash58
splash58

Reputation: 26153

set argument for constructor

$d = new \DateTime("midnight");

UPD: if an object already exists with any time

$d->settime(0,0);

result

DateTime Object
(
    [date] => 2016-04-20 00:00:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)

Upvotes: 53

Related Questions