Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the bug on created_at in the customer_entity table on update #4070

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

sdecalom
Copy link
Contributor

@sdecalom sdecalom commented Jul 2, 2024

This pull request can fix the bug on created_at in the customer_entity table on update.

Description (*)

Since MySQL 8.0, we have had a problem with the created_on column in the customer_entity table. In the beforeSave() function, we have the date in a timezone format ==> 2010-04-21T07:42:19+00:00. However, after the update, if your MySQL is set up with time_zone='+02:00', your created_at will not be in UTC.

So, the solution is to remove the timezone format.
"2010-04-21T07:42:19+00:00" ==> "2010-04-21 07:42:19"

By doing this, the created_at field with time_zone=+2 we have a bad result

UPDATE customer_entity SET created_at = '2010-04-21T07:42:19+00:00' WHERE entity_id=5;
-- Result: 2010-04-21 09:42:19

By doing this, the created_at field will maintain the correct value.

UPDATE customer_entity SET created_at = '2010-04-21 07:42:19' WHERE entity_id=5;
-- Result: 2010-04-21 07:42:19

Related Pull Requests

Fixed Issues (if relevant)

  1. Fixes Bug on created_at in customer_entity table on update #4069

Manual testing scenarios (*)

  1. ...
  2. ...

Questions or comments

Contribution checklist (*)

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All automated tests passed successfully (all builds are green)
  • Add yourself to contributors list

fix bug on created_at in customer_entity table on update
@github-actions github-actions bot added the Component: Eav Relates to Mage_Eav label Jul 2, 2024
kiatng
kiatng previously approved these changes Jul 6, 2024
@fballiano
Copy link
Contributor

I was trying to test this, but with or without this PR I always get the data saved in mysql wrong by 1h (9.15 is stored but it's 10.15 here now).

system timezone is set correctly and if I do SELECT NOW() I get the right time. timezone is also set correctly in openmage settings.

mmmm

@pquerner
Copy link
Contributor

pquerner commented Jul 6, 2024

Anything you do in Magento is UTC by default.
\Mage_Core_Model_App::_initEnvironment

@fballiano
Copy link
Contributor

@pquerner ye ye I know but I live in the london timezone, but I recognize now that the can still be a difference between london and UTC, which I didn't think was possible

@pquerner
Copy link
Contributor

pquerner commented Jul 6, 2024

But you meantioned you did a SELECT NOW() - which is outside of Magento. So it will most likely tell you your OS timezone. Or whatever you did tell MySQL what your timezone is. Just wanted to clarify.

@fballiano
Copy link
Contributor

timezone in mysql is "SYSTEM"

@kiatng
Copy link
Contributor

kiatng commented Jul 7, 2024

I tested with the following script:

        $object = Mage::getModel('customer/customer');
        $attribute = $object->getResource()->getAttribute('created_at');
        $now = Mage::getSingleton('core/date')->date('Y-m-d H:i:s'); // My locale time zone is +8:00 in OpenMage.

        // Test datetime value is null
        $attribute->getBackend()->beforeSave($object);
        $createdAt0 = $object->getCreatedAt(); // Expect UTC datetime

        // Test datetime value in local time zone
        $object->setCreatedAt($now);
        $attribute->getBackend()->beforeSave($object);
        $createdAt1 = $object->getCreatedAt(); // Expect convert $now to UTC datetime

        $r = [
            'now' => $now,
            'created_at0' => $createdAt0,
            'created_at1' => $createdAt1,
        ];

Result before PR:

 array(3) {
  ["now"] => string(19) "2024-07-07 20:47:03"
  ["created_at0"] => string(19) "2024-07-07 12:47:03"
  ["created_at1"] => string(25) "2024-07-07T12:47:03+00:00"
}

After PR:

 array(3) {
  ["now"] => string(19) "2024-07-07 21:03:12"
  ["created_at0"] => string(19) "2024-07-07 13:03:12"
  ["created_at1"] => string(19) "2024-07-07 13:03:12"
}

Datetime in UTC are set and ready to be saved to DB. So both sets of results seem correct to me.

@kiatng
Copy link
Contributor

kiatng commented Jul 7, 2024

Ref earlier doc MySQL 5.7 has no time zone specification. But [MySQL 8.0] doc](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-literals.html) has it

Beginning with MySQL 8.0.19, you can specify a time zone offset when inserting TIMESTAMP and DATETIME values into a table. The offset is appended to the time part of a datetime literal, with no intravening spaces, and uses the same format used for setting the time_zone system variable, with the following exceptions:

  • For hour values less than 10, a leading zero is required.
  • The value '-00:00' is rejected.
  • Time zone names such as 'EET' and 'Asia/Shanghai' cannot be used; 'SYSTEM' also cannot be used in this context.

If I interpret this correctly, before v8.0, time zone offset is ignore. After v8.0, MySQL will do conversion using the offset and the config param time_zone. You can see the conversion example in the doc. It has this snippet to check the time zone:

SELECT @@system_time_zone;`
# Result in my DB: +08

I do another test MySQL 8.0.37

Without setting created_at

        $object = Mage::getModel('customer/customer')
            ->setData([
                'firstname' => 'John',
                'lastname' => 'Doe',
                'email' => '[email protected]',
            ])
            ->save();
        print_r($object->getCreatedAt());

With created_at, for example during data import.

        $object = Mage::getModel('customer/customer')
            ->setData([
                'firstname' => 'John1',
                'lastname' => 'Doe',
                'email' => '[email protected]',
                'created_at' => Mage::getSingleton('core/date')->date('Y-m-d H:i:s'),
            ])
            ->save();
        print_r($object->getCreatedAt());

Result Before PR:
image

Result After PR:
image

Conclusion: Both sets of result are correct, meaning this PR is not needed in my test environment.

@sdecalom Any idea what server params I miss?

@sdecalom
Copy link
Contributor Author

sdecalom commented Jul 8, 2024

@kiatng, any idea.

For my side in MySQL server I have this configuration
image

In DB I have this
image

In afterLoad()
Value of date => 2021-03-17 19:58:47
image

Value of created_at => 2021-03-17T20:58:47+01:00
image

Value of created_at => 2021-03-17T19:58:47+00:00 in beforeSave()
image

But in DB I have 2021-03-17 20:58:47 instead of 2021-03-17 19:58:47
image

For my example, we have a difference of one hour

@addison74 addison74 changed the title Fix bug 4069 Fix the bug on created_at in the customer_entity table on update Jul 8, 2024
@kiatng
Copy link
Contributor

kiatng commented Jul 9, 2024

My review of @sdecalom screenshots:

Screenshot 1 @@system_time_zone is set to local time zone, same as what I have.

Screenshot 3 `afterLoad()` result is correct

Value of date => 2021-03-17 19:58:47

Comment: the initial value as stored in the DB, the time zone is UTC

Value of created_at => 2021-03-17T20:58:47+01:00

Comment: the value after converting to local time zone with the UTC offset +01, meaning your local datetime is 2021-03-17 20:58:47.

I confirmed the above is a correct result with Windows Copilot and Gemini AI. My prompt is

Given datetime "2021-03-17T20:58:47+08:00", what is my local time

I have changed the UTC offset to my local time zone in the prompt.

Screenshot 4 `beforeSave()` result is correct

Value of created_at => 2021-03-17T19:58:47+00:00 in beforeSave()

I am not familiar with the IDE, my guess is that the initial value is $date = '2021-03-17T20:58:47+01:00'. This is in local time zone. And the resulted value $zendDate->getIso() is '2021-03-17T19:58:47+00:00'. This is correct as we want to save datetime in UTC.

Screenshot 5 DB value is incorrect

But in DB I have 2021-03-17 20:58:47 instead of 2021-03-17 19:58:47

Conclusion: you are correct, the value in DB should be 2021-03-17 19:58:47. However, I cannot replicate this in my test:

    public function indexAction()
    {
        $var['date'] = '2021-03-17T20:58:47+08:00'; // Note my time zone is UTC +8
        $object = Mage::getModel('customer/customer')->load(18);
        $object->setCreatedAt($var['date'])->save();
        $var['after_saved'] = $object->getCreatedAt();
        $object->load($object->getId());
        $var['after_load'] = $object->getCreatedAt();
        Zend_Debug::dump($var);
    }

output:

array(3) {
  ["date"] => string(25) "2021-03-17T20:58:47+08:00"
  ["after_saved"] => string(25) "2021-03-17T12:58:47+00:00"
  ["after_load"] => string(25) "2021-03-17T20:58:47+08:00"
}

image

@pquerner
Copy link
Contributor

pquerner commented Jul 9, 2024

Anyone checked what happens when you load customers via collection?

@kiatng
Copy link
Contributor

kiatng commented Jul 9, 2024

Anyone checked what happens when you load customers via collection?

    public function indexAction()
    {
        $var['date'] = '2021-03-17T20:58:47+08:00';
        $object = Mage::getModel('customer/customer')
            ->getCollection()
            ->addAttributeToFilter('entity_id', 18)
            ->getFirstItem();
        //$object->setCreatedAt($var['date'])->save();
        //$var['after_saved'] = $object->getCreatedAt();
        //$object->load($object->getId());
        $var['after_load'] = $object->getCreatedAt();
        Zend_Debug::dump($var);
    }

result:

array(2) {
  ["date"] => string(25) "2021-03-17T20:58:47+08:00"
  ["after_load"] => string(19) "2021-03-17 12:58:47"
}

Mage_Eav_Model_Entity_Attribute_Backend_Time_Created::afterLoad() is skipped, datetime is UTC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Eav Relates to Mage_Eav
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug on created_at in customer_entity table on update
5 participants