Problem/Motivation
The datetime views plugins have wonky timezone support. This needs to be fixed. While most evident in the argument plugins, the filter, and sort plugins have similar problems.
Proposed resolution
Because of coupling with the views architecture, fixing the individual plugins with separate issues is essentially impossible. In addition, a proper fix means moving some backend specific code out of the generic Sql class (date handling in SQL is not equivalent between the supported databases), and fixing some date support in Views itself.
Remaining tasks
Cry, then fix all the things and provide test coverage.
User interface changes
None.
API changes
\Drupal\views\Plugin\views\query\Sql::__construct() now accepts a parameter DateSqlInterface $date_sql to provide a database-specific date handler. Implementations for MySQL, PostgreSQL, and SQLite are provided as services.
The Drupal\views\Plugin\views\query\QueryPluginBase class has two new methods:
- setTimezoneOffset()
- getTimezoneOffset()
and the signature for \Drupal\views\Plugin\views\query\QueryPluginBase::getDateField() has been updated to account for offset calculations.
Data model changes
None.
Original Report
The datetime View Arguments don't take into account the user's timezone. That means that if you make a View that has \Drupal\datetime\Plugin\views\argument\YearDate argument then all users will same events even if the timezone for a user would push certain events into either the next or previous years.
This is probably an edge case for years but for the new arguments in #2567815: Add week, date, and year-month Views argument plugins would be more effect by this.
So if you used the FullDate argument then dates that would be in a different day because of the user's timezone don't show up correctly.
Working on a patch
| Comment | File | Size | Author |
|---|---|---|---|
| #308 | 2627512-8.4.x.patch | 62.1 KB | jibran |
| #296 | 2627512-296.patch | 60.2 KB | jofitz |
Comments
Comment #2
tedbowOk it uses the MySQL function UNIX_TIMESTAMP to convert the string dates to timestamp.
Then it calls
$this->query->getDateField($timestamp_field);Which is the same method that \Drupal\views\Plugin\views\HandlerBase::getDateField use since it starts with a timestamp.
So the timezone conversion would be the same for core date field and datetime field.
Of course this only works if we can find ways to do the same thing in pgsql and sqllite.
Comment #3
mpdonadioThanks for the patch. Couple quick thoughts.
This needs test coverage, and preferably a test-only patch demonstrating the problem, too. (NW for this part).
Not sure if adding a switch here is the best thing to do. What if someone wants to add support for Oracle or a NoSQL database in contrib? I think adding a method onto the database driver class may be the best thing to do. Going to try to raise a DB maintainer for an opinion.
Comment #4
chx commentedA) these plugins are already SQL bound, heavily so
B) within SQL , instead of amending the database layer every time you can use the backend override mechanism and define services like
then injecting $container->get('foo') will get the right version. If someone writes the Oracle driver, they can just add an oracle.foo service. It's not magic, it's Drupal 8 :) Check BackendCompilerPass or talk to me if it doesn't make any sense.
Comment #5
Crell commentedNyet. If you need the DB connection, inject it.
That said, chx is correct. Any time you find yourself tempted to switch on $db_type, make a backend_overridable service instead.
Shameless plug: https://www.palantir.net/blog/d8ftw-customizing-your-back-end
Comment #7
tedbow@Crell @chx thanks for the guidance on this.
I was basing my code on \Drupal\views\Plugin\views\query\Sql::getDateField
But I am rewriting now to take in the suggestions above.
Thanks
Comment #8
tedbowOk here is a patch with suggestions from @crell and @chx, thank again.
I had no idea about backend_overridable tag, very cool.
The patch creates 2 services datetime.date_field and mysql.datetime.date_field
It creates and interface \Drupal\datetime\DateFieldInterface
There is the default implementation of the service is \Drupal\datetime\DateField
This service acts exactly like the current logic.
return "$date->tableAlias.$date->realField";Then there is the MySQL implementation of the service \Drupal\datetime\MySQLDateField
Which uses UNIX timestamp to convert the string date to an int so that the regular View logic for timezone offsets can be used.
return $date->query->getDateField(" UNIX_TIMESTAMP( {$date->tableAlias}.{$date->realField}) ");Presumably if I am on the right track then I would still need to write Postgre and sqlLite implementation of the service.
The default implementation of the service still does not take into account timezone offsets as it is the same as the current logic.
Comment #10
Crell commentedThat's much more like it, Ted!
1) The generic implementation should probably be called GenericDateField, rather than DateField, since we assume it will likely never get used.
2) Having a service for one single-line method seems wasteful, even if it is the correct approach here. Do we expect there to be other date-time-related DB branching? Perhaps we should generalize this class from a Views class to a generic class in core somewhere that Views can use, and we can add other date-time-related DB methods to it? Or is this logic Views-specific? Not sure on this one.
Comment #11
tedbowThanks, definitely doesn't feel as dirty ;)
Makes sense renamed in this patch.
I don't know the datetime module that well. I did search and didn't find any other the text "sqlite" and "mysql" in the module and didn't find it.
In the Views module itself there is
\Drupal\views\Plugin\views\query\Sql::getDateFormat
\Drupal\views\Plugin\views\query\Sql::getDateField
\Drupal\views\Plugin\views\query\Sql::setupTimezone
which all are all date related and all have conditional statements based on Database::getConnection()->databaseType()
In that case would it make sense to have a service in views with separate implementations for backends and have the 3 functions needed for Views and the 1 needed for DateTime in that same interface?
Comment #12
Crell commentedFactoring all of those switch statements out to a single swapped service seems logical, yes, since they would all change together. What those methods are doing now is unquestionably wrong. :-)
Comment #13
mpdonadioMy spidey sense tells me that we may have some more MySQL specific date handling in core that doesn't have test coverage (a lot of Date and Views code was straight port w/o refactoring as D8 evolved), so it may or may not be working in PG or SQLite. I think adding something to centralize SQL date functions in the \Drupal\Core\Datetime namespace makes the best sense in the long run, rather than sticking this in with Views.
I would say we keep make the service w/ one function in this issue to address the bug, so we can get it into 8.0.x. Then make a followup to handle Database::getConnection()->databaseType() usage relating to date functions, and target it for 8.1.x.
Comment #14
tedbow@mpdonadio that seems like a good idea as far as getting this into 8.0.x. Then it might be easier to move it a Views service later.
Then again maybe it makes some sense to have the datetime service remain different from a new service in Views for date because the datetime is the only place in Drupal core that stores date time as ISO string. Right?
Regarding this patch is it only considered finished if we have a PostgreSQL and SQLite implementations of the service. They should work they same as they did before but of course would still have the user timezone bug.
I can pretty easily setup a site with MySQL to test but haven't use PostgreSQL before. I was wondering if there was a Vagrant box I could use for Drupal PostgreSQL development. Ideas on that?
Comment #15
mpdonadioSetting NR so TestBot runs. Here is an interdiff between #8 and #11. Still need tests to demonstrate the problem.
Comment #16
mpdonadioUntested. Just me reading the manuals for PostgreSQL and SQLite to stub out the files, and haven't tacked tests yet.
Still torn about keeping this Views centric, or making it more generic to live somewhere else.
Comment #18
mpdonadioLet's see if this fixes PostgreSQL. Help via @pwolanin.
Comment #22
jhedstromThis gets the Postgresql test passing. However, now it is entirely dealing with integer timestamps on the backend, which is probably ok, but a change nonetheless.
I also cleaned up some updated coding standards here.
Comment #23
jhedstromHaven't had a chance to look at the SQLite fails. The PostgreSQL fails are because the changes in #22 to
Sql::getDateFormat()impact more than just the argument plugin, so they break (filter and sorting).Comment #24
jhedstromI wonder if we could push all of the db-specific switch statements in
\Drupal\views\Plugin\views\query\Sqlinto these backend-overridable plugins as part of this fix?Comment #25
mpdonadioI don't see why not? The SQL class shouldn't have to know about these types of details.
Comment #27
jhedstromThis steps back from the datetime-specific backend overridable date field services, and moves them further up the stack into views. It doesn't yet address the bug here. The issue is that the offset is calculated in
Sql::getDateField(), yet in the datetime module we skip that method entirely in the sort and argument date plugins:So somehow (probably a new public method to
Sql) we need to be able to get that offset in the datetime plugins.Comment #31
jhedstromRe-uploading to queue against 8.2.x.
Comment #34
jhedstromThis adds a test, and a fix. It could probably still use some unit tests for the new date sql service that was introduced above.
Comment #35
jhedstromOops, just realized MySQL and SQLite will fail spectacularly on the above patches :) Fixes for those 2 coming soon.
Comment #36
jhedstromI think this has MySQL and PostgreSQL passing. SQLite needs work. (Re-uploading the test-only patch as it wasn't properly queued in #34).
Comment #39
jhedstromThis is turning into quite the issue. If we do the proper fix for arguments, it impacts the sort and filter plugins (which currently do not properly support timezones, although filter sort of does).
Comment #40
mpdonadioSo, we essentially have to rescope this to cover all three set of plugins in order to fix the original bug?
Comment #41
jhedstromre #40 I think that would be the best way to approach this. As I dig in, the timezone support is all over the place for datetime (the filter plugin does a conversion in code to UTC, while the sorting plugin ignores it entirely). If we are able to fix most of this in the views sql plugin, that seems ideal. Thoughts?
I should have something with more tests passing tomorrow.
Comment #43
jhedstromThis should have improvements in all 3 db backends. String date handling is now done natively in the sql plugin, rather than hacked in at the datetime plugin level, so it should be much cleaner.
Comment #45
jhedstromThe fails on mysql & sqlite were related to the date-only storage test. Now that timezone offsets are properly calculated, the test failed for the test timezone (Australia/Sydney). To address this, a new parameter was added to
Sql::getDateField()to switch off timezone calculation.The other fails on pgsql look random.
Comment #46
jhedstromThese additions were necessary for the
FieldAPIHandlerTraitmethods to work properly on datetime's argument plugins.Comment #47
jhedstromThe pgsql fails look totally unrelated...and it looks like 8.2.x already has some fails on pgsql?
Comment #48
jhedstromThis adds unit tests for the 3 database-specific date query plugins.
Comment #49
mpdonadioAssuming this come up green (or just the PGSQL randoms), do you think this is ready for review? We want to get @dawehner or @tim.plunkett for final review since have delved into the bowels or Views now.
Comment #50
jhedstrom@mpdonadio it's ready for initial review anyway. I'm guessing there will be some tweaks needed once there are more eyes on this.
Comment #51
mpdonadioWow. Not really seeing anything here; this is awesome work. The webtest looks good, covering a date changeover b/c timezone. The unit tests on the new classes look good, too. Going to ping some people for other looks, since this is some major refactoring.
Maybe expand this to explain why?
Maybe explain why this is needed?
Note to self, use Prophecy more :)
Comment #52
jhedstromUpdating the title to reflect that this is all datetime Views plugins, rather than just arguments.
I also think this meets the criteria for a major issue since it would impact any site using configurable timezones, and datetime fields with views.
Comment #53
dawehnerReally great work is going on here!
Just an example: those examples docs should better describe why something is done, not what its doing.
Nice test!
On the longrun (not part of this issue at all) it would be nice if this interface would actually be part of the database system itself. Nothing here is bound to views itself, which is really nice!
Can we provide a default implementation? Otherwise classes extending this class will break.
Does this mean Sql.php effectively implements
DateSqlInterface?Nice improvements!
Just nice!
Comment #54
jhedstromThanks for the detailed review!
Comment #56
mpdonadioLooked at latest patch, tests, and think this is good to go. I think my involvement in the current version of this patch has been limited to comments (think all of my code is now gone), so I don't see an issue with setting RTBC on this. If anyone disagrees, set back to Needs Review and we will see if we can get someone else to look at it again.
Comment #60
gambryI see the hard work done so far, but the bug still persists for Date-only field and Views filter.
How to reproduce:
- Add a 'Date only' date field.
- Create a entity using today as date, i.e. 2016-07-15.
- Create a View, with a filter for the date field above and 'Is equal to' as operator
- Filter the View using 2016-07-15
You won't get any result (it will work if search for 2016-07-16).
I need to mention my timezone is Europe/London, not sure if does or doesn't affect the calculation, but the can reproduce the test on simplytest.me.
The reason is due the date being saved as 2016-07-15 onto the DB, but the query looks for
DATE_FORMAT('2016-07-14T23:00:00', '%Y-%m-%d')Not sure how to fix this. I can suggest few options when datetime type is
DATETIME_TYPE_DATElike validating the user input - i.e.:strtotime($input) > 0- and using the raw input value without formatting OR adding the offset to the UNIX timestamp so$this->dateFormatter->format()calls will calculate the right date.But I'm sure there is a better D8 way.
Comment #61
jhedstrom@gambry can you try this again now that #2739290: UTC+12 is broken on date only fields is committed?
Comment #62
gambry@jhedstrom I'm assuming running a 8.2.x instance + patch at #54 from simplytest includes both works. And the issue persists.
I'm now running a local instance just to double check.
UPDATE:
Yes, issue is still there.
The problem lives on how
strtotime()defaults to the server time zone if a time zone parameter is not specified. So for instance appending 'UTC' would force strtotime() to read the string as UTC, fixing the issue.Comment #64
gambryHere a patch with the test to demonstrate this. The additional test use nodes dates values as view filters (testing both '=' and 'between' operators) and it fails.
I've also attached a possible patch, including the additional test and a fix. As mentioned on #62 the problem is
strtotime()using the default/server timezone to render the UNIX time from the string, which can or can not be UTC.The patch append
DATETIME_STORAGE_TIMEZONEto the filter values in order to force the conversion to be done in UTC. I've applied the fix only on the Filter plugin, but I'm assuming other plugins have got the same issue and need to be fixed too.PS: I've been using D8 since 5 days so I'm sorry for best practices or not-logical mistakes. Feel free to swear.
Comment #67
gambryI've updated the patch in order to pass all tests, however I think generally there is something going wrong on the "time string -> UNIX timestamp -> ISO" conversion, at least on the Date views filter.
If you run the tests core/modules/datetime/src/Tests/Views/FilterDateTest.php when your request time is 1 min after midnight, on some scenarios they fail.
For example using REQUEST_TIME as 1468710060 which would be a 'now' if ran at '2016-07-17 00:01:00' from Europe/London timezone, but it's '2016-07-16 23:01' for UTC which the SQL renders as '2016-07-16' on its selects.
My original patch - appending DATETIME_STORAGE_TIMEZONE to all filter values for date-only fields - could potentially fix the issue, but it's impossible to use concurrently with $origin > 0 according with this:
I'm also looking at
$this->calculateOffset = FALSE;as another potential cause. I understand we don't deal with time for date-only dates, but during the filtering process we do a lot of conversions from/to time based values (the time strings, the UNIX times, the SQL date function parameters), so I think an offset calculation somewhere in the stack can be the solution.Comment #70
gambryRemoving hardcoded leftover.
Comment #71
mpdonadioHere is the interdiff between #54 and #70.
Comment #72
jhedstromThanks @gambry for picking this up!
Simply appending the timezone as a string here makes me nervous, since the input could potentially be something that doesn't deal well with that.
What if instead we drop
strtotimeentirely, and use something along the lines of:$a = new DateTimePlus($value);and then set the timezone to the storage timezone for date-only fields with the
setTimeZone()method on the datetime objects.We can then convert to a timestamp using
$a->format('U').(This will simplify the implementation of #2749483: Datetime views filter plugin should allow granularity to be configurable too I think.)
Nit: comment needs to wrap at 80 characters.
Comment #73
gambryI made a conceptual code in order to test the statement above and indeed it fails.
The idea is for 'now' time string to be Today at 00:01.
I won't add this test to the patch queue because it would start looking messy, I'll leave it here for you to read and see my point, may be running locally and add to the patch later.
Comment #74
mpdonadioI would advise using DateTimePlus() instead of the native functions if we can. Once we get the time service in core (can't find issue now), then testing will be a lot easier. Overriding the builtins is a royal pain.
Comment #75
gambryI'll work on this asap. In the meanwhile have you got any suggestion RE the issue at #73?
Basically relative dates - i.e. 'now' (20th July 2016) - can actually be different - i.e. becoming 19th July 2016 - when converted to ISO passing from UTC timezone.
I think we do need to cover 3 scenarios then, with different requirements:
Comment #76
gambryAttached my changes.
I'm using DateTimePlus() as suggested, I've also corrected the > 80 chars comment and also introduced the test at #73.
I just want to flag the FilterDateTimeTest() tests twice a scenario when view date filter operator is 'between' but there isn't a 'min' value.
However I can't replicate this from the UI.
Trying to create a filter without specifying a 'min' value raises a validation error (both min and max are required), and as exposed filter filtering without 'min' ignores it at all.
So ideally test should be removed or - at least - documented as "not replicable from the UI".
Due a big difference between how strtotime() and DateTimePlus() process
""as date string (1970-01-01 00:00:00 the first, 'now' the last), the test above forced me to add the following line in the filter/Date::opBetween():Comment #78
gambryfixing Drupal\Tests\views\Unit\Plugin\query\SqlTest, adding $date_sql parameter to instance at line 404.
Comment #79
mpdonadioReviewing interdiff-54-76.txt to just look at the last set of changes.
I don't see how $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME') and REQUEST_TIME are ever different, so the $origin_offset will always be 0? Few times in the patch.
Since we are avoiding strtotime() in the patch b/c TZ weirdness, we should probably avoid it here, too. Seems to be that we can get the value, convert it to a timestamp, and then just add / subtract fudge factors to simulate the edge cases.
Scratching my head here on whether this is a valid change. Storage is always DATETIME_STORAGE_TIMEZONE (UTC), and the widgets / formatters convert back and forth when dealing with fields, so it doesn't seem right that we are using the user TZ here and saving that right into the field value.
Thoughts on all of this?
Comment #80
gambryI think the idea of
$this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME')is to get a mock-up-able REQUEST_TIME value to use as origin, feature I actually use in FilterDateTest::testDateOffsetEdge*().They will be different as soon as something changes the RequestStack REQUEST_TIME value, and I think we should consider the difference.
I'm also calculating the offset - and not the origin as before - because DateTimePlus doesn't take origin parameter on processing relative date string. The offset is added later on right before using the timestamps.
I agree. I'll change it as soon as everybody is happy with the review.
Yes, storage is always UTC.
And specifically when storing 'date' type dates the system doesn't convert the values, considering them UTC since the form submission.
But when the view filters process the value(s) they use the user/default timezone (before with strtotime() as well as now with DateTimePlus()).
The change is needed for all the tests using the dates values as filters. If we use UTC on creating the values, then we have to change the user/system timezone to UTC right before executing the view.
As I think the idea of the test is to simulate the closest possible the UI/UX, I felt more reasonable using the user's time zone on creating the dates values.
To test this it's easy, just compare
$this->nodes[1]date value (today) with its generated storage query condition to see their gap. Before #78 the values are different, potentially causing error described on #73.I understand it looks like a continuous ping-pong of TZ conversion, however it kind of makes sense and mainly it's the only reasonable way I can see to get all tests/scenarios pass.
Comment #81
mpdonadioYes, getting the REQUEST_TIME via the current request is the best practice.
Nobody should ever be changing the value of the REQUEST_TIME outside of tests. In fact, the global is (hopefully) going to be deprecated soon (see #2717207: Add a time service to provide consistent interaction with time()/microtime() and superglobals). I think we can ignore the difference and simplify the logic here.
The problem is, that the test isn't matching what is really going on. I think it would be better if the test takes the REQUEST_TIME and user timezone into consideration, and then ensures that the values that gets into storage is correct, without those lines changing. The net result should probably be the same values, but we can comment the process to make it very clear what is happening and why (which is very important in tests).
And please don't take this as harsh. This was a very good catch, and I think this patch is very close now and shows good work. We have just had way too many TZ related problems that I want to be extra careful that we don't just get a passing test. I want to ensure that our tests demonstrate as close as possible what really goes on (especially in ones like these where they are closer to kernel tests that true integration tests) and also prevent future regressions.
Comment #82
gambryThe problem is I'm not aware of any function other than strtotime() taking in consideration an origin parameter.
And as we dropped strtotime() the only way to consider the requestStack REQUEST_TIME other than the original REQUEST_TIME on processing relative date strings is to calculate their offset with
$this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME') - REQUEST_TIME, to be added to the date timestamp.If we remove the
- REQUEST_TIMEbit than we need to either:- Remove the tests where we change the requestStack REQUEST_TIME (FilterDateTest::testDateOffsetEdge*())
- Rethink the whole $origin consideration on processing relative dates with DateTimePlus().
Open to any suggestion.
I'm not sure if here you are still referring to the REQUEST_TIME offset bit or to using the user TZ instead of UTC on the test.
The test now takes the user TZ into consideration and as we are dealing with 'date' types there isn't any storage conversion on saving them.
Can you be a bit more specific?
Please be! I don't mind. We are developer after all, we have the rights to be rude. :)
And honestly we all want this issue to be sorted - may be before 8.2.x window closes - so everybody should be aware of the pressure for producing a high quality patch.
Comment #83
mpdonadioI think we can remove that particular set of tests. When we get the time service in core, we can look into better coverage of edge cases.
I am not comfortable with this hunk:
since it it not mirroring what is going on inside the widget. I think we can alter the code that computes `static::$date` to better mimic what is going on inside DateTimeWidgetBase, and end up with the same value, so that there is no change to the tests themselves.
.
Since this is a bug, this can get into core at any time, but I do know a lot of people are anxious to get this wrapped up.
Comment #84
gambryI got your point. I felt free to use a different timezone as the DateTimeWidgetBase for DateTimeItem::DATETIME_TYPE_DATE is TZ agnostic, so whatever TZ you input either on the widget or directly saving the node is not converted.
And just for clarity the reason I opted for the user TZ is instead of the storage one is due the 'today' created with
\Drupal::service('date.formatter')->format(static::$date, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE),not being equal with the 'today' created with the 'now' string in the offsets tests.While the 'today' created with
\Drupal::service('date.formatter')->format(static::$date, 'custom', DATETIME_DATE_STORAGE_FORMAT, drupal_get_user_timezone())it is equal.I'm seeing only 3 solutions in here:
1. Using the drupal_get_user_timezone() on creating the date values.
2. Restoring DATETIME_STORAGE_TIMEZONE on creating the date values and using it as user/default TZ so relative conversions work.
3. Restoring DATETIME_STORAGE_TIMEZONE on creating the date values and considering the offset between the user TZ and UTC while calculating the`static::$date`.
I see option 1 more linear and self-explaining, 2 is totally to be dropped because the aim of this issue is to consider timezones other than UTC, 3 better mirrors the date widget and I think it's the one you are proposing here, correct?
So far I've collected these reviews/changes:
- Removing the $origin calculation, until we get the time service in core.
- Removing edge tests, until we get the time service in core.
-
Replacing strtotime() call with DateTimePlus on edge tests(suppressed from change above)- Implement solution 3 from the list above.
If you are happy I'll apply these changes.
Comment #85
mpdonadio#84, I think that sounds like plan to wrap this up, but I pinged @jhedstrom to see if he has any additional thoughts on this.
Comment #86
jhedstromI agree that option 3 in #84 is the way to proceed here, since as noted it mimics the behavior in the date widget and formatters.
Comment #87
gambryAttached the reviewed patch.
To simplify review against original jhedstrom's patch at #54 I've attached the interdiff with that as well.
Comment #90
jhedstromThis is looking great. Thanks @gambry!
I'll leave it for @mpdonadio to do the final RTBC.
Comment #91
mpdonadioI think this looks good and RTBC, but I am looking at this and wondering if the 'now' in the hunk above will lead to spurious fails, instead of something derived from REQUEST_TIME.
Maybe
would be safer? Middle line is there because TZ is ignored with @ formats...
Comment #92
mpdonadioNo, that hunk is just getting the timezone offset from the \DateTime; you can use just about anything there near REQUEST_TIME and get the same value. The parameter is so that the calculation works for dates where time zones (the named ones, not the offset) have changed DST rules / handling (we actually have test coverage of this somewhere).
Think this is good to go, and test coverage is good, and comment #36 has a test-only patch that shows that this is a real bug.
We just entered 8.2.x beta. According to https://www.drupal.org/core/d8-allowed-changes#beta, this is allowed per
as this is a non-disruptive bug fix.
I do not think this is safe to assume this works with 8.1.x b/c #2739290: UTC+12 is broken on date only fields changed the way date-only worked, and I would be OK with this just getting into 8.2.x.
Comment #101
gambryThe issue seems to live here, on the '+' sign.
Tests run on Australia/Sydney timezone which is UTC +10, Australia/Sydney 10:01 am = UTC 00:01 am.
So when a date value is processed by the date.formatter service, the format() method adds the offset again. Consequently $static::date needs to be
REQUEST_TIME - offsettoo.Tests never spotted this because #87 patch has always been tested before Australia/Sydney midnight! :)
#78 has been tested out of this range, but its test didn't have this code/bug.
I won't update the patch yet as (1) I would like to have your thoughts and (2) I want to test a TZs with negative offset to see if
REQUEST_TIME - offsetworks as well.Comment #102
gambryI forgot to mention locally tests pass subtracting the offset, instead of adding.
Comment #103
mpdonadioLet's add the time zone loop like we do in the field tests to make sure we really squash this.
Comment #104
gambryI made a POC of test which seems to work for all timezones.
The core of the change is:
REQUEST_TIME + timezone_offset_get(new \DateTimeZone(drupal_get_user_timezone()), new \DateTime('now', new \DateTimeZone(DATETIME_STORAGE_TIMEZONE)));becomes
REQUEST_TIME - abs(timezone_offset_get(new \DateTimeZone(drupal_get_user_timezone()), new \DateTime('now', new \DateTimeZone(DATETIME_STORAGE_TIMEZONE))));subtracting the absolute value of the offset.
The rest of the changes are due date values calculations and storage can't stay on setUp() anymore.
My understanding is we can't have @dataProvider on WebTests, so I made my best to keep everything clean and clear.
Comment #107
jhedstromThe patch in #104 seems to have lost the new sql date plugins (thus the fails).
Comment #108
gambrySorry. Re-uploading.
Comment #110
gambryTests pass subtracting the offset when UTC time value is pm, but adding when value is am.
At least we - hopefully - hit the bottom.
Before updating the patch with a weird sign switcher, I want to see if it's possible to get UTC equivalent timestamp of user's 'now' using DateTimePlus() instead of working out the right offset with awful code.
Comment #112
gambryOn the test I've replaced this bit:
with a DateTimePlus() implementation.
After re-factoring #78 I lost a required bit for offset type date filters, and I think last errors were due to that being missing.
Tests pass locally, I've been also changing my machine date setting to test all TZs at different time/date.
Comment #113
gambryI've been manually adding tests to cover different time ranges. All pass successfully.
I've just added last one now and if passes as well I think we just need:
- a test-only patch again, for double checking.
- a review of FilterDateTest() re-factoring, after including TZs loop. #108 interdiff.
- a review of the re-added missing part. #112 interdiff.
- a beer and a honest burger to everyone.
Comment #114
jhedstromThese updates look good to me. Leaving for @mpdonadio for final review.
Comment #115
mpdonadioTook me a while to understand what was going on with the last set of interdiffs to handle the TZ loop, but I think we are good to go.
Comment #116
gambryIt's my fault as I was assuming the fix for the Date filter was OK and issue was in the test and specifically the way we calculate the current users date as UTC timestamp.
I was wrong so my comments between #101 and #111 are not to be considered.
#112 corrects both as I restored the right code fix and re-factored the way we calculate the date, using DateTimePlus().
Thanks for reviewing and sorry again for the mess.
Comment #118
andypostNeeds asap reroll
faced with the issue trying to use sqlite
Drupal\Core\Database\DatabaseExceptionWrapper: Exception in Episodes Next Last[episodes_next_last]: SQLSTATE[HY000]: General error: 1 no such function: UNIX_TIMESTAMP: SELECT node__broadcast_time.broadcast_time_value AS node__broadcast_time_broadcast_time_value, node_field_data.nid AS nid, node_field_data.langcode AS node_field_data_langcode FROM {node_field_data} node_field_data LEFT JOIN {node__duration} node__duration ON node_field_data.nid = node__duration.entity_id LEFT JOIN {node__broadcast_time} node__broadcast_time ON node_field_data.nid = node__broadcast_time.entity_id WHERE (( (node_field_data.status = :db_condition_placeholder_0) AND (node_field_data.type IN (:db_condition_placeholder_1)) AND (UNIX_TIMESTAMP(node__broadcast_time.broadcast_time_value) + node__duration.duration_value >= :time) )) ORDER BY node__broadcast_time_broadcast_time_value ASC LIMIT 4 OFFSET 0; Array ( [:db_condition_placeholder_0] => 1 [:db_condition_placeholder_1] => episode [:time] => 1472563553 ) in Drupal\views\Plugin\views\query\Sql->execute() (line 1488 of /srv/core/modules/views/src/Plugin/views/query/Sql.php).Comment #120
vprocessor commentedrerolled
Comment #121
andypostBack to rtbc
Reroll bacause of #2721901: Fix Drupal.Commenting.FunctionComment.MissingParamName
Comment #122
xjmThis issue does include API additions / internal changes, so it should be targeted against 8.3.x at this point.
Really great to see all the test coverage.
Comment #125
alexpottWe're not supposed to combine @inheritdoc with other docs - this is just not supported by api.d.o. We should just move the comment inside the method.
I've not got time to finish my review. If another committer thinks the rest of this patch is okay - maybe just fix that on commit.
Comment #126
alexpottDo we need a change record for contrib/custom modules that are extending the date plugins changed in this patch? I think so.
Comment #127
jhedstromChange record added: https://www.drupal.org/node/2813317. Can somebody review and bump this back to RTBC?
Comment #128
mpdonadioA lot of this relates to the CR. I may be misreading some of these (not reviewing it in place right now).
@alexpott, how much detail do we need in this CR? Can we just mention the new DateSqlBase / DateSqlInterface, and that database backends need to implement, or do we need to go into all of the gory details here?
Needs to be mentioned in CR?
Needs to be mentioned in CR?
API change on a public function, so needs to be mentioned in CR?
API addition, needs to be mentioned in CR?
API addition, needs to be mentioned in CR?
Added a plugin parameter, so I guess we need an empty hook_update_N() to force a container rebuild?
Comment #130
jhedstromChange record added for the new date handling interface, and changes to the Views query plugin: https://www.drupal.org/node/2818693
Comment #131
jhedstrom@mpdonadio suggested an update hook be added to force the service container to be rebuilt, which makes total sense.
Comment #132
jhedstromThe update hook needs to be on views, since that's where the change is.
Comment #133
mpdonadioOK, I think the CR is adequate to announce the low level changes to Views, and we can adjust as needed if there are questions. Think this is ready again.
Comment #134
mpdonadioAre we going to consider this for 8.2.x, too? Not sure if it is too disruptive. If not, then we need to consider a sort-term fix for 8.2.x, #2825127: Views exposed filter on date only field gives incorrect results.
Comment #136
mpdonadioI think these are known, random fails related to update tests.
https://www.drupal.org/pift-ci-job/531288
https://www.drupal.org/pift-ci-job/523908
https://www.drupal.org/pift-ci-job/531327
Comment #138
mpdonadioChecking to see if there is a general testbot problem right now, but noticed this:
Rer @catch:
And per @catch the post-update hook can be empty in this case to achieve the same thing.
Comment #139
jhedstromComment #140
jhedstromFails seem completely unrelated. Missing schema files, etc? Seems like the testbot ran out of storage or something...
Comment #141
xjm@dawehner, @tim.plunkett, @alexpott, @cilefen, and I agreed that this is a major bug.
Reuploading @jhedstrom's patch to retest, which should be with 5.6 now.
Comment #142
mpdonadioDid a quick re-review, and still think this is RTBC.
Comment #144
mpdonadioResetting RTBC b/c https://www.drupal.org/pift-ci-job/572210 looked like an unrelated CI error.
Comment #145
bkosborneAdding #2786577: The Views integration Datetime Range fields should extend the views integration for regular Datetime fields as a related issue. This issue is currently blocking progress on that one.
Comment #149
bkosborneI think I found an error here. I guess this line was copied from the orBetween method, but the array key for accessing the value is incorrect.
Comment #150
mpdonadioIf #149 comes up green, then we have a problem with test coverage.
Comment #152
mpdonadiohttps://www.drupal.org/pift-ci-job/585127 b/c a known random fail.
What baffles me is why this didn't trigger a fail, before or after.
FilterDateTest uses date-only fields, and the simple/offset variants of filtering, so the code path in the interdiff should have been hit and at least triggered a notice, which would cause a test fail.
?
Comment #153
gambry'min' is a valid array key, and by default is an empty string. So PHP shouldn't trigger the notice.
Tests should also pass because as #92 states you can pass to that chunk almost anything. It just needs a valid Datetime object to create the timezones offset.
Am I correct?
I agree it should change to something else, may be 'value' is a good candidate, but if my observation is correct we should also mention it in a comment.
Comment #154
mpdonadio#153, yeah timezone_offset_get() needs the second argument to compute the offset for a particular date, as the offset for zone names can change. There have been very few in recent times, which is what I mostly meant in #92. And, yes, min/max are defaulting to empty strings, so no notices.
I eyeballed this again in-place, and think the code-change in #149 is good. Reviewing this again applied, I don't think it is worth contriving a test to cover this rare edge case. I also think the code is clear and commented enough.
I'm setting this back to RTBC. We need this patch in.
Comment #157
andypostfirst it needs to be commited to current dev branch
Comment #158
mpdonadioI thought bugs, esp triaged majors, could get into the 8.3.x first at this point and then cherry picked to 8.4.x?
Comment #159
andypost@mpdonadio not sure about "alpha stage" so 8.3 or 8.4 but anyway first commit should go to 8.4.x and then backport, mostly always commit should go to current dev
BUT I see php7 tests fail
Comment #160
mpdonadioRetriggering the PHP7 tests because they look unrelated JSTB fails:
https://www.drupal.org/pift-ci-job/586861
https://www.drupal.org/pift-ci-job/586862
https://www.drupal.org/pift-ci-job/586863
I'll create a f/up, but these look like they could be from the yet-to-have-an-issue mentioned in #2829040: [meta] Known intermittent, random, and environment-specific test failures and #2843693: Random test failure in CKEditor AjaxCss.
Comment #161
acbramley commentedHad a very similar issue to what is described in #60 (on 8.2.5) and #149 fixed it nicely.
Comment #162
acbramley commentedI've found a bug with this with relative dates.
I have a view with relative date filters:
- Date is greater than or equal to "first day of this month"
- Date is less than or equal to "last day of this month"
This results in the following query after the patch:
DATE_FORMAT(node__field_date.field_date_value, '%Y-%m-%d') >= DATE_FORMAT('2017-02-02T10:37:57', '%Y-%m-%d')) AND (DATE_FORMAT(node__field_date.field_date_value, '%Y-%m-%d') <= DATE_FORMAT('2017-03-01T10:37:57', '%Y-%m-%d')) ))Which has clearly been affected by timezones after being converted from the relative string.
Comment #163
mpdonadioIs that a date+time field or date only? Should be pretty easy to add test coverage for this.
Comment #164
acbramley commented@mpdonadio that's date only, if no one else gets to it by this afternoon I can have a stab at the tests
Comment #165
mpdonadio#162, I think the problem is that those aren't relative dates. Relative dates are supposed to be offsets from the current time. "First day of month" and "Last day of month" are dynamic dates, but not offsets from the current time. When I choose offset, I see the problem you posted; when I choose date in any machine readable format", I get what I expect (and I am in the window now where it is "tomorrow" UTC).
@jhedstrom? @gamby? Thoughts. I don't think this is a code bug, just due to the fact that the help text on those widgets isn't clear (think I made an issue about that a few days ago).
Comment #166
acbramley commentedEDIT: It seems to be working now, I think I missed applying the patch before testing (monday-itis) which means that we definitely need to update those descriptions as the functionality has changed for each option with this patch.
Comment #167
gambryI don't think this is a code bug, just due to the fact that the help text on those widgets isn't clear (think I made an issue about that a few days ago).PHP documentation mix these as well so I'm not sure how we can better explain than what the descriptions already say.
However I think any Relative Format should be used only on offset and this is because those formats are relative to the user (or the website) TZ.
I.e.: First day of the months for UTC+1 at 2017-03-01 00:00:01 !== First day of the months for UTC at the same UNIX timestamp.
The plugin will calculate and apply the offset accordingly.
And in fact if I use the values at #162 with type offset it works, although I've only tested for my TZ which is UTC+0 so I'm not reliable.
Then if I'm correct we can update the description of the offset type linking the allowed PHP relative formats and we need to fix the bug, if any.
#166 are you saying using the patch + still offset types it works?
UPDATE:
Using any relative date format different than an offset (i.e. now +1 day) results in a wrong calculation with both types:
datethe offset is not considered, so the resulted date is relative to UTC:i.e.: 2017-03-01 00:14 Pacific/Kwajalein - first day of the month - DATE_FORMAT('2017-02-01T12:14:14', '%Y-%m-%d')
offsetthe offset is considered, but as the relative format is resolved at the beginning the offset is applied to the UTC date:i.e.: 2017-03-01 00:14 Pacific/Kwajalein - first day of the month - DATE_FORMAT('2017-02-02T12:14:14', '%Y-%m-%d')
Not sure how to react to this problem.
Comment #168
jhedstromIf the findings in #167 are caused by this patch, then we need additional test coverage and a fix. If it is already an issue without this patch, then let's pursue that fix in a follow-up and get this in, as it is quite a major blocker for a lot of folks.
Comment #169
mpdonadio#168, I don't know how we can really address this w/in the scope here since we would now be messing with a broader portion of Views (all of dates, not just datetime) and potentially string changes. Since we take text input and stuff it into `new DateTimePlus()` a user can type in just about anything. And, with string input, I don't know how we can differentiate relative versus non-relative input.
Maybe this just needs a CR to announce the behavior change, and outline the pitfalls of relative dates and using things like "first day of month" for entry?
My suggestion is to get this patch in, and create a f/up to improve the UX of these plugins, both from a user input perspective and help text perspective. This is a hard patch to review as it is, I think followups are the best option.
Ideally, I think `Drupal\views\Plugin\views\filter\Date` needs to be adjusted to use the '#datetime' form element for 'date' values, and '#text' for the relative option. For datetime fields, we would adjust the datetime form to just show the date for date-only. We could also have some shenanigans to switch out the '#datetime' for a '#text' if someone wants to do 'first day of this month'. And then, combine this with better help text. All of that can probably done without any b/c concerns, and we can do it in 8.4.x where we can do string changes.
Comment #170
acbramley commented#167here's a retest of several scenarios (with more coffee):
My timezone is Australia/Melbourne (UTC+10) and it's around 09:00AM on 7th February. I'm using a date only field.
With the patch applied (from #148)
Options set to "an offset from the current time", I get:
"first day of the month" translates to 2017-02-02T09:00:27
"last day of the month" translates to 2017-03-01T09:00:27
Options set to "a date in any machine readable format", I get:
"first day of the month" translates to 2017-02-01T22:01:55
"last day of the month" translates to 2017-02-28T22:01:55
Without the patch applied:
Options set to "an offset from the current time", I get:
"first day of the month" translates to 2017-01-31T22:08:32
"last day of the month" translates to 2017-02-27T22:08:32
Options set to "a date in any machine readable format", I get:
"first day of the month" translates to 1970-01-01T00:00:00
"last day of the month" translates to 1970-01-31T00:00:00
So you're right, with the patch the correct option to use is "a date in any machine readable format", and before the patch the offset option was broken anyway.
As you say though it would be very hard to detect a relative date with everything just being a string, I agree that this should be broken off into a separate follow up issue.
Comment #171
jibranUploading a patch for 8.2.5
Comment #172
mpdonadioSetting back to RTBC, and made #2850276: Improve the UX of the Views Date plugins as the followup. I postponed it initially; not sure if anything else we have in the pipeline also needs to block it.
Comment #174
gambryApplying suggested change from #2851902: Replace $date->format('U') with $date->getTimestamp().
And as format() returned a string while getTimeStamp() returns an integer we don't need the intval() wrappers anymore as well.
Comment #179
mpdonadioNeeds re-reroll b/c #2248983: Define the revision metadata base fields in the entity annotation in order for the storage to create them only in the revision table. Should be easy hand merge in core/modules/views/views.post_update.php
Comment #181
gambryThis is the re-roll of #174. As #2248983: Define the revision metadata base fields in the entity annotation in order for the storage to create them only in the revision table already defines a hook_post_update_NAME for 8.3.x group I'm not 100% sure what the best practices are here: if still keeping the empty hook or being happy with the other one triggering the cache rebuild.
However as I'm not sure they will be released in the same minor version - and anyway better safe than sorry - I left the views_post_update_date_sql_service() in.
This is a re-roll after all so there shouldn't be any code change.
Comment #183
mpdonadioLooks like a good re-roll. Took another quick look at patch and still think this is RTBC.
I'm not going to do the back-and-forth w/ the version, but since this is a major triaged bug, it should be 8.3.x eligible, even after 8.3.0 gets tagged. I think this is an important bug, so I am adding "rc target triage" to see if we can get this into 8.3.x-RC1.
A committer will have to make the final call of where the post update hook goes. That can be a fix-on-commit, and some empty ones have been getting stripped out anyway in cases where another post update hook is there.
Comment #184
xjmThanks @mpdonadio. As mentioned we're just going to look at issues discretionarily after commit for RC now. Although, dang, this poor issue has had a rough time bouncing into and out of the RTBC queue over months.
It's not a small patch though and is an addition, so it will probably be 8.4.x only. Hopefully we can get it landed in 8.4.x soon though because it's been disrupted so many times by so many things and I can only imagine how frustrating that is. :( Thanks for highlighting the importance of the issue.
Comment #185
xjmNote on https://www.drupal.org/core/d8-allowed-changes#patch it says:
That applies even to major bugs. And then all of these things are minor-only:
https://www.drupal.org/core/d8-allowed-changes#minor
Edit: I totally get though that this issue has been RTBCish for a long time including since right around the alpha and also on and off before that. Several other Views major bugfixes are in that category as well, unfortunately.
Comment #187
gambryRe-rolling due #2776975: March 3, 2017: Convert core to array syntax coding standards for Drupal 8.3.x RC phase
Comment #188
gambry#187 is missing unversioned (new) files, besides git for some reason added some trailing spaces. Re-uploading same patch as #181 with only the changes due #2776975: March 3, 2017: Convert core to array syntax coding standards for Drupal 8.3.x RC phase.
Comment #190
mpdonadioBig patch, and this comes up green; a lot of work went into the test coverage. I eyeballed this, too. I think this is a good re-roll.
Comment #193
jofitzRe-rolled.
Comment #194
mpdonadioThanks for the quick reroll.
Looks like some cruft from the got into the patch with the `git add -A`. Otherwise, this looks good.
Comment #195
jofitzOops, I got a bit sloppy there.
Comment #197
jibranPatch to patch 8.3.x. Please ignore.
Comment #199
Pavan B S commentedLine exceeding 80 characters
Did minor change of coding standard to the #197 , suggest me if i am wrong.
Comment #201
jofitzSetting back to RTBC because the patch in #195 has not changed - the two patches since are not relevant to 8.4.x.
@PavanBS in future it is probably not worth correcting coding standards in a patch that someone has marked "please ignore".
Comment #202
mpdonadioThe patch in #199 is 5k smaller than #195 and #197, but with a one line interdiff. When I get to work I will look into this and make sure the proper patch gets final review.
Comment #203
jofitzAha, I now see what @PavanBS was trying to correct, but he somehow managed to delete a few files by accident too.
@mpdonadio would you like me to update the patch in #195 (there are also a couple of coding standards issues too)? Or shall I just leave it with you?
Comment #204
jofitzThe changes were so straightforward that I went ahead and made them anyway. I hope you don't mind @mpdonadio.
Comment #205
mpdonadioThis is a complex patch. I'm pretty confident we have good test coverage, but I won't have time to give it proper attention until tonight to make sure we didn't break anything or introduce any out-of-scope changes.
Comment #206
mpdonadioCompared #195 (the last RTBC patch) and #204 very closely, and they are all in-scope changes to the issue. This is a hard patch to run phpcs on, since it touches so much, but I still think this is OK. Before we polish this any further, lets see what a committer says. So, re-rolls only when absolutely necessary (true test failure b/c another issue or patch doesn't apply). And, if one of these does happen, please post what you had to adjust in the patch. For rerolls, the output from the rebase helps a lot. Thanks.
Comment #207
pwolanin commentedI'm getting a fatal from core/modules/datetime/src/Plugin/views/argument/Date.php when I apply this patch to 8.3 in combination with #2325899: UI fatal caused by views argument handlers no longer being able to provide their own default argument handling
Possibly the patch here should add the create() method in addition to the constructor?
Or at least, whichever patch goes in first, the other will need a fix.
Comment #208
mpdonadioOdd that ArgumentDateTimeTest doesn't fail. The Drupal\datetime\Plugin\views\Argument\Date class currently extends Drupal\views\Plugin\views\argument\Date, which has a create method and implements ContainerFactoryPluginInterface. But, #2325899: UI fatal caused by views argument handlers no longer being able to provide their own default argument handling removes those.
Gotta think some more about this.
Comment #209
pwolanin commentedI think it's ok to leave this at RTBC. The additional fix to the other patch to make it work together was tiny (remove the 4th constructor arg).
Comment #211
mpdonadioWhoever triggered the retest, do you have a link to the failed job so we can see what the failure was to see if it is a known one or a new one?
Comment #212
jibranRe-rolled for 8.3.0. without the post-update hook.
Comment #214
mpdonadioReuploading patches for bot runs.
2627512-214-w-update.patch has the post-update, and apples to 8.4.x
2627512-214-wo-update.patch doesn't have the post-update, and apples to 8.4.x and 8.3.x
Comment #215
mpdonadioPG fails were fixed in #2867887: statistics_get() test mashes 0 too much. This is still RTBC.
Comment #216
bkosborneHeads up to anyone applying this patch to their composer-managed drupal install via the composer-patches plugin... the new files this patch introduced will not be stored in the proper location. See https://github.com/cweagans/composer-patches/issues/43 for more information on why.
Comment #217
generalconsensus commentedI'm currently working on https://www.drupal.org/node/2868014 and the copious amount of tests required to make it succeed. I'm unsure on how best to proceed for tests that need to test hour and minute level granularity. The test date is created with UTC but the opSimple and opBetween methods assume that the timezone will only be UTC for date inputs that are restricted to 'Y-m-d'. This is a problem since my dates will include 'Y-m-d H' and 'Y-m-d H:i'. The code works in views but fails in the tests since timezones for those dates are always derived from drupal_get_user_timezone which for me differs from UTC considerably. Should we rethink just passing in the date values and allow for passing in a timezone as well? I don't want to impede this ticket from continuing but I don't want to take us in the wrong direction with my next patch if some reason I might be wrong in my thinking. @mpdonadio
core/modules/datetime/src/Plugin/views/filter/Date.php:101
core/modules/datetime/src/Plugin/views/filter/Date.php:145
Comment #218
mpdonadio#217, the code you show in #217 is primarily related to #2739290: UTC+12 is broken on date only fields. Basically, for the date-only flavor of datetime fields, the timezone is ignored (ie, the date is always in the local time for the user). For date+time fields, the timezone offset is applied. This patch enforces this behavior in views.
So, I suspect you have two problems in #2868014: [PP-1] Views Date Filter Datetime Granularity Option. One, is that it sounds like you are blocked on this issue (at least soft blocked). Two, you need to account for both date-only and date+time field options, and adjust the choices appropriately and then test the right cases.
Comment #219
generalconsensus commentedI was able to fix my testing issue with the following code that was introduced in the above patch:
Comment #221
mpdonadioMore known randoms. Back to RTBC.
Comment #224
mpdonadioOK, reroll is b/c #2863267: Convert web tests of views.
Rolled back to c2f6edd, remove the hunks for FilterDateTest, applied 2627512-214-w-update.patch and rebased that against 8.4.x.
Then hand edited the FilterDateTest hunks to account for the move, and did a `git apply -3` to get them in. And adjusted the setup a smidge to install the node_access schema.
Passes locally...
Looks good to me, but need to see what the bot says. If these pass, I'll add the tests for the other DB backends.
These will no longer apply to 8.3.x b/c #2863267: Convert web tests of views was only against 8.4.x.
Comment #227
mpdonadioOK, here's a fix. Should be fully green now. Had to rework ArgumentDateTimeTest a bit now that it is a KTB. See interdiff for the change.
Comment #229
alexpottFlowing all the comments to 80 chars.
I'm not sure this abstract class has any point - just for a constructor? It adds complexity and obfuscates dependencies for no gain.
This doesn't exist meaning that if there is no matching backend it is going to fall over. I think mysql should just be the default.
These don't need to be public services.
Patch attached addresses all of the above.
The one remaining question for me is how can we make the views.date_sql more internal and say that it functionality should only be accessed via the SQL query plugin?
Comment #231
mpdonadioBefore I forget:
Comment #232
gambryI understand what the issue is, but I'm not sure what the solution could be.
I don't find any reference to backend overridden services working differently than what we have in here (i.e.
entity.query.sqllooks working in the same way), so I'm struggling to find what the best solution would be.We don't want people to inject views.date_sql into anything but as long as it's needed by
Drupal\views\Plugin\views\query\Sql::create()we can't avoid it.What about changing
plugin.manager.views.queryservice and/orDrupal\views\Plugin\ViewsPluginManagerso we can pass views.date_sql by argument? That gives us the freedom to set views.date_sql as private.Additionally, is this a blocker? IMHO this looks like a big chunk of decision + changes so better in a follow up?
We could leave a comment in the views.services.yml telling the developers to NOT inject views.date_sql as will be marked private soon.
Comment #234
mpdonadioI think for the time being, I think we should just mark these as internal.
Comment #235
jibranCan we create something similar to what
\Drupal\Core\Entity\Query\Sql\QueryFactoryis doing?s/in in/is in.
We should add a comment here. Also, I think 19700101 should be a constant.
Comment #237
mpdonadio@jhedstrom or @gambry, re 235-2 do you remember why we are adding the field in seconds to the epoch? I can't make a query excercise this logic to see what is happening in real life in the SQL.
@jibran, I looked at QueryFactory and am a little stumped if something similar can be done here. That is a factory, these are just dependencies for a plugin. Perhaps they could implement a get() method that gets used in the Sql() constructor that checks the caller class? If we mark as @internal they we can defer to a f/up?
Comment #238
gambry#237 I wasn't involved on writing the Sql plugins, but I guess that's because base [created, updated, timestamp] date fields storage type is UNIX timestamp, so we add the timestamp (seconds from epoch) to the epoch and return the date to compare with.
See
Drupal\views\Plugin\views\HandlerBase::getDateField()for usage. All other usages set the$string_dateTRUE as they use a different storage type.Comment #239
gambryThis patch addresses feedback from #235.
RE: "The one remaining question for me is how can we make the views.date_sql more internal and say that it functionality should only be accessed via the SQL query plugin? " it looks like the best solution is to use
@internalinitially and re-work the way plugins are called and the arguments passed in a follow-up. Is that correct?Comment #241
jhedstromI've given this another review and it looks good. +1 for RTBC from me.
Comment #243
larowlannit ===
language is off here
I might be missing something here, but how is the pgsql/sqlite one substituted? Its not reference in the change record - so we definitely need some docs around that - I assume its making use of the backend_overridable tag?
Comment #244
mpdonadio#243-1,2 addressed. Yes, 3 is from a backend_overridable. See #4 and #5; updating CR shortly.
Comment #245
mpdonadioTook a pass at updating the CR w/ info about
backend_overridable.Comment #249
Anonymous (not verified) commentedAwesome work here! This issue can also block the #2325899: UI fatal caused by views argument handlers no longer being able to provide their own default argument handling, because it allows to save us from careless refactoring (#92), and (most importantly) makes the work of the repaired handlers more reliable (#102). Thanks!
Comment #250
karenann commentedI am still working in the 8.3.x branch (currently 8.3.7) and the patch in #244 did not apply cleanly.
This is an attempt to reroll it for 8.3.x.
There were 4 files that triggered an "can't find file to patch".
The new locations of these files appeared to be:
With that, I was able to match up, manually apply, and then generate the patch with only one exception where the code didn't clearly contain the hunk referenced.
Comment #253
mondrakeWith the patch in #244
#247, core Kernel tests for the 'views' group error out if run on a contrib database driver that does not implement MySql syntax for dates SQL (with the patch in #2605284-107: Testing framework does not work with contributed database drivers applied). Apparently MySql is the default unless a module specifies an alternative service, so you won't be able to run core tests as such.See e.g. https://travis-ci.org/mondrake/drudbal/builds/269690110?utm_source=githu...
EDIT: corrected patch reference
Comment #254
tacituseu commented#244 is the patch to review.
Edit: Nevermind, now I see #253 is based on patch from #244.
Comment #255
xjm#253 is failing dramatically. There are no further commits to 8.3.x. Uncrediting that reroll since it isn't working (but thanks for giving it a shot!)
Also uncrediting @Pavan B S's patch since it was a coding standards change on a patch that was not even part of the issue's progress.
I do think this needs to be 8.5.x now. (Edit: Sorry we didn't get a chance to look at it during alpha.)
Can we reupload the correct patch for 8.5.x as the last patch on the issue so it gets RTBC retesting?
Comment #256
mpdonadioPatch from #244 applies cleanly, but applied it anyway and did a fresh diff and it is indeed idential (or at least interdiff thinks so).
Tweaking CRs momentarily.
Comment #257
xjmThanks @mpdonadio. Setting back to RTBC since the previous patch was (I didn't review it myself.)
Comment #258
mpdonadioPer #262 and #247, set RTBC.
Comment #259
mondrakeLet me clarify my comment in #253.
This patch makes things complicated for contrib database drivers.
AFAICS, the choice to have the date functions as plugins means a module should provide alternative non-core plugins for date functions of other db platforms. But a database driver is not a module. A contrib db driver should then also provide a module with the appropriate plugin.
IMHO, it would be preferable to move date functions to db drivers like suggested in #2657888: Add Date function support in DBTNG. This would also have the benefit of making date functions accessible outside of views.
Not changing from RTBC as I appreciate the huge work done here and I understand this comment comes very late. Also maybe this can be done on a second stage.
Comment #260
xjmThanks @mondrake. I agree with having a separate issue for that.
Comment #261
DrupalDude777 commentedHello,
I know Drupal 8.4.rc1 is already released and that we will soon have 8.4.0 and I thought that this specific #244 patch would have been applied to this stable version but when checking the code of 8.4.rc1, I don't see it.
Now I see there is already a patch for Drupal 8.5 in dev for this issue.
I was wondering why the patch has not been applied to 8.4 as it has passed all tests?
I would rather not hack Drupal core but I really need this patch to be applied.
Do you think it would be possible to include it in the official Drupal 8.4.0 release or could you tell me when it will be applied to any Drupal 8 next stable release?
Thank you in advance for your reply.
Comment #263
mpdonadioSmall merge conflict in core/modules/views/views.post_update.php
Comment #264
gambry#256 failure is due
function views_post_update_entity_link_url()in core/modules/views/views.post_update.php introduced by #2810097: Allow views to provide the canonical entity URL of all entities, not just nodes..Re-roll in #263 looks good. Thanks.
Comment #266
gambryPatch fails to apply due #2913957: Fix invalid casing in date argument's namespace. According with #2913957 comment #4 "Also looks like all of the `use` and related usages are OK." so trying a simple case change of
namespace Drupal\datetime\Plugin\views\Argument;to "argument". Hopefully tests will confirm this.Comment #269
mpdonadioMinor merge conflict from #2916451: Move everything related to Bulk Form to Views module in views.post_update.php
Comment #271
mondrakeI've posted a patch in #2657888-14: Add Date function support in DBTNG that does #259. Personally I think it would help making this patch simpler, too.
Comment #272
jhedstromRe-factoring this to be more general was added as a follow-up in #2745197: Move date SQL handling from Views to core database system. I've marked that as a duplicate of #2657888: Add Date function support in DBTNG, but IMO that need not block this fix from going in, as mentioned way back in #53.
Comment #274
jofitzPatch in #269 no longer applies. Re-rolled.
Comment #276
xjmAs I posted on #2786577: The Views integration Datetime Range fields should extend the views integration for regular Datetime fields: This has been struggling in the RTBC queue awhile, because the issue is big, the patch is big, and it's difficult technical subject matter. :P It might help if one of the other Views maintainers could review it and give an explicit signoff if everything looks good to go. I'm leaving it at RTBC because I don't think this is 100% a requirement; just something that might help.
Comment #277
dawehner🔧 Suggestion: We could actually move this calculation onto
hook_views_datatime and as result we need to do less on runtimeComment #278
xjm#277 sounds significant enough to be worth exploring, thanks @dawehner.
Comment #279
gambryIf we do what suggested in #277, then any module extending datetime fields views plugins will require to have that code in its hook_views_data() while at the moment all of them will benefit from this code being in the plugins. Is that correct?
Worth saying the helper in #2786577: The Views integration Datetime Range fields should extend the views integration for regular Datetime fields may help on avoiding this redundant requirement, but these two issues are becoming chicken-and-egg so maybe #277 is a good followup when both are in?
Comment #280
jhedstromThe change suggested in #277 while appearing trivial, would be a pretty big refactor of this patch.
Can we explore doing this conversion in a follow-up since the approach to the patch here has not changed all that much in the past 18 months since it was first RTBC? I'm worried that such a big refactor might further postpone getting this bug fixed, and the performance gains of the alternate approach would be minimal (at first analysis anyway) since the field storage definitions are loaded regardless of this settings check.
Comment #281
mpdonadioI have been looking at #277 for bit, and would prefer to do this in a followup. I share the same concerns in #279 and #280. Also, this seems to violate the purpose of hook_views_data(), which is just to "Describe data tables and fields (or the equivalent) to Views."
Comment #282
catchAgreed in looking at #277 in a follow-up, hook_views_data() isn't our happiest hook so keeping logic out of it seems sensible. Going to try to review this properly soon.
Comment #283
jibranReroll for 8.4.2. Please ignore
Comment #285
mpdonadioNeeds reroll b/c #2901562: Fix 'Squiz.WhiteSpace.SuperfluousWhitespace' coding standard. Starting patch is in #274.
Comment #286
mpdonadio$ git checkout 8.5.x
$ git pull
$ git checkout 3af361c83c622ed618328ebde2c8a25f26ea419e
$ git rebase origin/8.5.x
First, rewinding head to replay your work on top of it...
Applying: asdfasdf
Using index info to reconstruct a base tree...
M core/modules/datetime/src/Plugin/views/filter/Date.php
Falling back to patching base and 3-way merge...
Auto-merging core/modules/datetime/src/Plugin/views/filter/Date.php
CONFLICT (content): Merge conflict in core/modules/datetime/src/Plugin/views/filter/Date.php
error: Failed to merge in the changes.
Patch failed at 0001 asdfasdf
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Chose patch over HEAD.
Comment #289
gambryYep. That looks good. Below the only change:
Before (#274):
After (#286):
Thanks.
Comment #290
catchDid a first pass review of this. I haven't read all of the comments so apologies for duplicating any questions asked previously.
Is this comment still accurate for dates stored with offset?
The timezone and offset logic is done both here and in opBetween, is it worth a helper?
The backend_overridable stuff is a big step up from the inlined switch statement, but does it need more docs for database drivers?
Comment #291
mpdonadio290-1, currently storage doesn't have an offset or record the timezone. Those are #2716891: DateTimeIso8601::setDateTime() vs. DateTimeItem::schema(): (at least) one of them is broken and #2632040: [PP-1] Add ability to select a timezone for datetime field.
290-2, probably a good idea. Will wait for final feedback before doing anything.
Docs. We have an overview of this in the CR, #2818693: Date handling is now injected as a separate service to the Views SQL query plugin, which has the link to the CR for backend overrides #2306083: Backend specific services now have a standard way to override. What do you think could be expanded here?
Comment #292
xjmI took a few minutes to go through the issue and assign credit appropriately to reviewers and patch contributors who helped move this issue forward, so that task is out of the way for the committer (me or someone else) who eventually commits this.
Since this issue was also about to roll over to a second page of comments. I also took the time to delete unneeded comments on the issue (test failure comments, assigned comments or status changes with no other content, etc.). That shaved like 100 comments off. :)
Assigning to catch for review of #291.
Comment #293
catch#191 makes sense.
Had another read through, overall this looks good, it's also nice to see the switch statements replaced with backend_overridable.
Couple more small things:
Had some trouble with this comment and a couple of different ones, talking about user's now vs. UTC 'now' gets a bit existential. Is the situation just this?
- if a date is entered in the UI, because there's no timezone entry we need to calculate the offset for the user
- if using 'today' or 'tomorrow' we also need to calculate the range of those dates using the user's timezone.
If so, something like "Dates selected in the user interface have no timezone information, so apply the user's timezone offset here." might be enough?
Container rebuilds don't require a cache update, because the container cache is keyed off Drupal version - it will automatically get rebuild for any tagged release (and can use deployment_identifier for non-tagged releases).
CNW for those.
Comment #294
mpdonadio#290 and #293 should be addressed.
Comment #295
gambryThe filter code looks very nice now. Thanks!
Just two minor things.
Parameter tags should be grouped together. Just remove the empty line between them.
I know the offset is expressed in seconds, but should we mention it?
Comment #296
jofitzComment #297
gambryThanks.
All feedbacks from #293 and #295 are now addressed, back to RTBC.
Comment #299
tacituseu commentedUnrelated failure (#2926309: Random fail due to APCu not being able to allocate memory).
Comment #300
jibranPatch for 8.4.3. Please ignore.
Comment #302
jibran#296 is the right patch.
Comment #306
catchCommitted 4d629c4 and pushed to 8.5.x. Thanks!
Comment #307
jibranThis is a major bug so aren't we going to backport it?
Comment #308
jibranAnyway green patch for 8.4.x.
Comment #309
Anonymous (not verified) commented🎉🎉🎉 Fantastic pre-Christmas gift! Many thanks to everyone who helped with this!
Yes, it would be great to get it for 8.4 too. But thanks to @jibran for backports, now it is not so critical in this month ;)
Comment #310
catchIt's a major bug but the patch introduces new APIs, so I don't think we can do a straight backport.