date_entity_metadata_struct_getter() is used to convert all loaded field values to timestamps for Entity API metadata.

If I create a date field, using the 'date' field type (ISO date format), and set its lowest granularity to 'day', then the field has no timezone handling, and no timezone is stored.

However, debugging date_entity_metadata_struct_getter() shows this:

  // $item['timezone_db'] is the site timezone, not UTC
  $timezone_db = !empty($item['timezone_db']) ? $item['timezone_db'] : 'UTC';
  $date = new DateObject($value, $timezone_db);
  // $date is set for the site timezone.
  return !empty($date) ? date_format_date($date, 'custom', 'U') : NULL;

The result is a timestamp that is midnight in the site timezone. Converting it to UTC for date manipulation gives a time different from midnight, which skews calculations.

CommentFileSizeAuthor
#50 date-n2123039-50.patch5.78 KBDamienMcKenna
#48 date_timezone_test.tar_.gz1.51 KBRoSk0
#48 date-2123039-33-48-interdiff.txt2.08 KBRoSk0
#48 date-2123039-48.patch5.75 KBRoSk0
#33 interdiff-2123039-30-33.txt493 byteshgoto
#33 date-2123039-33.patch5.17 KBhgoto
#30 date-2123039-30-fix-and-tests.patch5.1 KBGold
#26 date-n2123039-26-tests-only.patch4.6 KBDamienMcKenna
#24 date-n2123039-24-info-only.patch372 bytesDamienMcKenna
#22 date-n2123039-22.interdiff.txt2.06 KBDamienMcKenna
#22 date-n2123039-22-tests-only.patch4.65 KBDamienMcKenna
#20 date-tests-for-entity-metadata-wrappers-2123039-20-test-only.patch4.67 KBGold
#17 date-tests-for-entity-metadata-wrappers-2123039-17-test-only.patch4.65 KBGold
#15 2123039-15.png78.08 KBhgoto
#14 interdiff-2123039-12-14-test-only.txt1.65 KBhgoto
#14 date-tests-for-entity-metadata-wrappers-2123039-14.patch5.17 KBhgoto
#14 date-tests-for-entity-metadata-wrappers-2123039-14-test-only.patch4.66 KBhgoto
#12 date-tests-for-entity-metadata-wrappers-2123039-12-test-only.patch4.21 KBGold
#10 date-tests-for-entity-metadata-wrappers-2123039-10-test-only.patch4.25 KBGold
#8 date-tests-for-entity-metadata-wrappers-2123039-8-test-only.patch4.23 KBGold
#5 date-tests-for-entity-metadata-wrappers-2123039-5-test-only.patch4.21 KBGold
#1 date-2123039-1.patch518 bytesRoSk0
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

RoSk0’s picture

This issue happens due to default timezone configuration in metadata wrapper.
Provided patch fixed this issue.

How to test:

  1. Attach "Date" field to some entity
  2. Run script similar to this:
    
    
    $entity = entity_create($entity_type, ['type' => $bundle]);
    
    $original = '1482721671';
    var_dump($original);
    
    $entity->wrapper()->{$field_name} = $original;
    $fetch = $entity->wrapper()->{$field_name}->value();
    var_dump($fetch);
    
    if ($original != $fetch) {
      print "WTF!!! Dates mismatch!\n";
    }
    else {
      print "Dates match!\n";
    }
    

Results without patch:

string(10) "1482721671"
string(10) "1482768471"
WTF!!! Dates mismatch!

Results with patch:

string(10) "1482721671"
string(10) "1482721671"
Dates match!

Would love to provide actual test coverage but need some guidance for it.

RoSk0’s picture

Title: date_entity_metadata_struct_getter() sets the site timezone on field values that should have no timezone » Default timezone setting mismatch in metadata wrapper integration

Setting proper title.

Juterpillar’s picture

Status: Needs review » Reviewed & tested by the community

Thanks RoSk0, that patch works for me.

RoSk0’s picture

Status: Reviewed & tested by the community » Needs work

Thanks @Juterpillar!
Moving to needs work because we need to create a test for this case.

Gold’s picture

I'm not entirely sure what's happening here.

I've added the tests to check the 3 date types (date, datetime & datestamp) and the tests are setting and getting the value from each field.

However... The tests pass.

I even rolled back to 7.x-2.10-rc1 which was current when date-2123039-1.patch was added. Tests still pass there too.

I may be doing something wrong here, but I'm pretty sure these are correct. Given how long this has been sitting here there's a chance that adding this patch may allow someone to tweak it.

Status: Needs review » Needs work
Gold’s picture

Ah nuts. Square bracket array declaration didn't kick in until 5.4. Rerolling...

Gold’s picture

Fixed the php 5.3 issues with the test-only patch.

Status: Needs review » Needs work
Gold’s picture

I really need to set up the local test env to work with php 5.3 too.

Caught the remaining square bracket array declarations.

Status: Needs review » Needs work

The last submitted patch, 10: date-tests-for-entity-metadata-wrappers-2123039-10-test-only.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Gold’s picture

Okay... that was embarrassing. Turns out it was copy & paste example code that threw the 'edit' module error.

Fixed that, updated the test name and tidied up the test output a little.

Gold’s picture

So... That worked. :/ It was supposed to throw errors that the application of this patch would fix.

@RoSk0, can you take a look and see why this is passing when it should be failing?

hgoto’s picture

I bumped into this issue. Thank you for the useful patches.

I tried the patch in #12 and it surely succeeds as unpexpected... I believe that we need to replicate the condition of the timezone handling in the test:

If I create a date field, using the 'date' field type (ISO date format), and set its lowest granularity to 'day', then the field has no timezone handling, and no timezone is stored.

I tried tweaking the patch. I'd like to see how the testbot says.

hgoto’s picture

Status: Needs review » Needs work
FileSize
78.08 KB

Hmm. The test-only patch in #14 fails as expected in my environment though...

Gold’s picture

I can confirm that I see the same errors you see in the image.

When I first ran it though, the Date Entity Metadata Wrappers test was not available. I had to manually enable Entity to get these to appear in the list.

Looking at the output from the test-only patch (click "Show: All") I don't see Date Entity Metadata Wrappers there either. While the test describes entity as being a dependency it appears to be used as a check to see if the test should be available rather than an indicator that it should add the module and enable it for the test.

I'm going to do a bit of digging to see how simpletest treats test_dependencies. It claims to handle it but I'm wondering if we're using it right.

Gold’s picture

Hmm... A check of the simpletest module returns zero hits for test_dependencies. Many for $info['dependencies'] though.

Testing that...

I still consider this to be Needs Work, but Needs Review will trigger the testing.

Status: Needs review » Needs work
Gold’s picture

Well that crashed and burned harder than expected.

Let's ignore the patch at #17.

The dig into simpletest continues...

Gold’s picture

Okay, lets see if it's the format of the of the test_dependencies[] entry.

Gold’s picture

Status: Needs review » Needs work

Nuts... That failed too.

If I understand it right we should see Date.DateFieldEntity in the list of tests. Check here for the test run and click All in the "Show: Failing classes All" line to see all the tests. The test does not appear. Can anyone see why?

DamienMcKenna’s picture

Status: Needs work » Needs review
FileSize
4.65 KB
2.06 KB

You need to clear the site's caches in order to have a new test file recognized.

Some minor tweaks to the test file.

DamienMcKenna’s picture

The tests fail locally:

Fail      Other      date_entity_metad  116 DateFieldEntityTestCase->testCheckE
    Date (ISO format) plays nicely with Entity Metadata Wrappers. 1482721671 ==
    1482685671
Fail      Other      date_entity_metad  116 DateFieldEntityTestCase->testCheckE
    Date plays nicely with Entity Metadata Wrappers. 1482721671 == 1482685671
DamienMcKenna’s picture

Ah! The tests don't run because the new dependency needs to be added to the module first. So lets do that first.

  • DamienMcKenna committed b7f4f0f on 7.x-2.x authored by Gold
    Issue #2123039 by Gold, hgoto, DamienMcKenna: Add Entity API as a new...
DamienMcKenna’s picture

Ok, now that the test dependency is committed we can now use it in the tests.

Status: Needs review » Needs work

The last submitted patch, 26: date-n2123039-26-tests-only.patch, failed testing. View results

DamienMcKenna’s picture

Ok, so now we're getting somewhere - the tests fail as follows:

  • fail: [Other] Line 116 of sites/all/modules/date/tests/date_entity_metadata_wrappers.test:
    Date (ISO format) plays nicely with Entity Metadata Wrappers. 1482721671 == 1482685671
  • fail: [Other] Line 116 of sites/all/modules/date/tests/date_entity_metadata_wrappers.test:
    Date plays nicely with Entity Metadata Wrappers. 1482721671 == 1482685671
Gold’s picture

Excellent. Thanks Damien.

So the Drupal test system checks out module, meets any dependencies and then patches. This feels like a bug report for that. :)

I'll recheck this with RoSk0s original patch now.

Gold’s picture

Gold’s picture

Status: Needs work » Needs review

The submission on this form really needs a check for "are you sure your Status is correct?" if a new file is added and the status doesn't change. :)

DamienMcKenna’s picture

Awesome work Gold, RoSk0s and hgoto! Test coverage to show the problem, and then a fix for the problem.

hgoto’s picture

Gold, Damien, Great! Thanks!! I didn't know that we need to add the new test dependency in advance.

I didn't add the assertion to confirm that the timezone setting is saved properly in the patch #14. Please let me add one line for that.

Gold’s picture

Status: Needs review » Reviewed & tested by the community

I didn't know that we need to add the new test dependency in advance.

That's what caught me out too. That was doing my head in. :)

New test looks sensible, patch still applies, tests pass.

I vote RTBC.

DamienMcKenna’s picture

Is there any possibility that $info['field']['settings']['tz_handling'] wouldn't exist?

Gold’s picture

I'm just adding a Date field now and the "Time zone handling" field has no empty values in the options. There is a value of 'none', but that should be stored.

Confidence is high that $info['field']['settings']['tz_handling'] would always exist if added from the UI.

Someone building a form in code may miss it though. But, IMHO, that would be a bug in their code.

This still feels RTBC to me.

  • DamienMcKenna committed 43d22cb on 7.x-2.x authored by RoSk0
    Issue #2123039 by Gold, hgoto, DamienMcKenna, RoSk0, Juterpillar,...
DamienMcKenna’s picture

Status: Reviewed & tested by the community » Fixed

Committed! Thanks everyone for helping to fix this!

hgoto’s picture

Great!! Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

joelpittet’s picture

Regarding #35/#36 I just ran into an issue where $info['field'] didn't exist, when loading from a token that was coming from a rule.

-  $timezone_db = !empty($item['timezone_db']) ? $item['timezone_db'] : 'UTC';
+  $timezone_db = date_get_timezone_db($info['field']['settings']['tz_handling']);

I think this may need a test for that case.

joelpittet’s picture

Also the function docblock mentions it returns UTC.

Getter callback to return date values as datestamp in UTC.

joelpittet’s picture

I think this patch needs a revert unfortunately. Nice that it has tests, just needs a bit more tests I guess or another approach.

DamienMcKenna’s picture

Status: Closed (fixed) » Needs work

Reverted. Thanks for catching that, Joel.

hgoto’s picture

@joelpittet, thanks. I tried to reproduce the case where $info['field'] does not exist with a rules config but couldn't. Can you please share a rules config I can reproduce the case with?

joelpittet’s picture

@hgoto, sorry for the delay. I've had this commit fail on two different unrelated sites, so there may be more cases where this is incorrect. But it's not the rule I think it's the token replacement where things break so I should be able to create a quick script to show that failure.

Please consider #42 indicates the output should be UTC I wonder why it even looks at the $item['timezone_db'] in the first place.

DamienMcKenna’s picture

So I think this needs more tests.

RoSk0’s picture

In regards to #42: Dates stored in DB in site default timezone - this is the reason why original code was looking for $item['timezone_db'] , but that doesn't change the fact that returned date is in UTC.

I added test for token replacement to confirm issue(actually there is not issues here and all works as expected).

Also, I wasn't able to reproduce issue with Rules. I have no test for it, but attaching with the rules config I used to test. I think whatever issues @joelpittet had with new code may be not in scope for this module/issue.

torotil’s picture

Status: Needs review » Reviewed & tested by the community

Looks good for me:

  • Resolves the issues for me ✓
  • Provides test cases ✓
  • Using the same method to determine the timezone in the setter and getter seems cleaner. ✓
DamienMcKenna’s picture

Rerolled, and I renamed the new test.

  • DamienMcKenna committed 6542675 on 7.x-2.x authored by RoSk0
    Issue #2123039 by DamienMcKenna, hgoto, RoSk0, joelpittet, torotil:...
DamienMcKenna’s picture

Status: Reviewed & tested by the community » Fixed
Parent issue: » #2867810: Plan for Date 7.x-2.11 release

Committed. Thanks everyone.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.