Magento – Magento 2 – Best practice to get current date

best practicedatemagento-2.0.5magento2

I have to save an updated_at attribute of a custom entity and to know which is the best practice I took a look at how Magento 2 handles it.

I looked at the \Magento\Eav\Model\Entity\Attribute\Backend\Time\Updated attribute backend model class and here is the code:

public function beforeSave($object)
{
    $object->setData(
        $this->getAttribute()->getAttributeCode(),
        (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)
    );
    return $this;
}

My first doubt is: which timezone is taken into consideration?

The signature of DateTime constructor is:

public DateTime::__construct ([ string $time = "now" [, DateTimeZone $timezone = NULL ]] )

According to constructor documentation:

If $timezone is omitted, the current timezone will be used.

I suppose that current timezone is the one configured at server level.

To prove that, simply execute the following PHP snippet:

<?php
var_dump(new DateTime());

The expected result is:

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2016-05-10 12:47:11.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(11) "Europe/Rome"
}

The Europe/Rome timezone is the one locally configured on my server.

But Magento 1 was used to save date and time according to GMT 0 so to have the confirmation that this approach has changed with Magento 2 I opened the \Magento\Eav\Model\Entity\Attribute\Backend\Time\Created and here comes the surprise:

public function beforeSave($object)
{
    $attributeCode = $this->getAttribute()->getAttributeCode();
    if ($object->isObjectNew() && $object->getData($attributeCode) === null) {
        //$object->setData($attributeCode, $this->dateTime->gmtDate());
        $object->setData($attributeCode, gmdate('Y-m-d H:i:s'));
    }

    return $this;
}

The created_at attribute for EAV entities seems to be saved according to GMT 0 timezone. The updated_at according to local timezone.

What's more there are two approaches in the Created backend model, one of which is commented.

My research for the best approach needs your help.
Thank you

Best Answer

That is very simple, since \DateTime object always contains a timezone, it is possible to translate it into UTC at any time, but unfourtunately Magento 2.0 code base does not do. Take a look at this core method in database connection that does a transformation: https://github.com/magento/magento2/blob/6ea7d2d85cded3fa0fbcf4e7aa0dcd4edbf568a6/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php#L2908 As you see it does call internally \Magento\Framework\Stdlib\DateTime to convert time into text representation. There are unfourtunately no timezone convertion is done.

I would recommend you to post a bug report, to have them fix that issue, as it must persist date always in UTC, as every store view can have own time zone configured.

Ideally, as with any other modern PHP ORM you should be able just to specify \DateTime object and the rest how it is stored should be processed by library itself, you as developer of business logic should not worry about the timezone conversions.

In my opinion \Magento\Faramework should convert all \DateTime objects in non UTC timezone into UTC time zone when stores data in database, and on frontend just change timezone for currently configured one, instead of having inconsistency over there. As well all filtration should convert datetime objects into UTC instead for database filtration.

Related Topic