9

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

1
  • can't believe your github issue never got any reply :-(
    – peedee
    Dec 5, 2016 at 6:57

3 Answers 3

3

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.

4
  • I did an experiment: I saved a new product on Magento 2 and then I updated it and both created_at and updated_at values are expressed in my local timezone. In Magento 1 those dates were saved in UTC. Since this is not "something that doesn't work" but "something that should work differently" do I have to open an issue on magento/magento2 GitHub repo or there is a different way? Sincerely Alessandro May 10, 2016 at 12:44
  • @AlessandroRonchi opening an issue on github is a right way, as well point a link to SO question and suggestion :) May 10, 2016 at 14:15
  • Any news on this?
    – Wouter
    Jul 7, 2017 at 12:13
0
 use Magento\Framework\Stdlib\DateTime\TimezoneInterface;

 class Retry extends \Magento\Framework\App\Action\Action
 {
         protected $yourDate;
         public function __construct(
            Context $context,
            TimezoneInterface $yourDate
         ) {
            parent::__construct($context);
            $this->yourDate =  $yourDate;
         }

         public function execute()
         {
          $currentDate = $this->yourDate->date()->format('Y-m-d H:i:s');
         }
 }
-1

Below solution is i have tried in Magento 2.1.2 CE & Works fine.

Go to file app\bootstrap.php, here end of the file u will find.

date_default_timezone_set('UTC');

Which is wrong, set to your ones

date_default_timezone_set('Asia/Singapore');

& Get Current Date Using

$magentoDateObject = $objectManager->create('Magento\Framework\Stdlib\DateTime\DateTime');
echo $magentoDate = $magentoDateObject->gmtDate();
1
  • This is wrong. Magento is supposed to work in UTC (because each store view can have a different time zone).
    – Wouter
    Jul 7, 2017 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.