Problem/Motivation
The 7.x Date module allowed the field to have an optional or required end date. D8 always requires the end date.
Proposed resolution
Make end_value in DateRangeItem optional, add validation constraint via configuration.
Key questions
5 key questions have recurred again and again over the life of this issue:
1. Is the start date optional too? NO
2. What value is stored in the end date property if it is left empty in the widget? NULL
3. Does the optional_end_date setting live in the field config or field storage config? FIELD CONFIG
4. How are optional and non-optional properties distinguished in the widget? STAR ON REQUIRED PROPERTIES BUT ONLY ON FIELD IF ALL REQUIRED
5. How are missing end dates displayed in the formatter? ONLY START DATE IS SHOWN
Remaining tasks
See the MR
Follow-up issues
- #3395096: Allow start date to be optional
- #3395100: Customise display of missing end date.
- #3401464: Date range should be in the date_time category
- #3404199: Improve UX of validation/constraints for daterange field
User interface changes
Field settings form:

Only start date is displayed when end date is missing:

History of discussion
#35 "I think we will have to `->setRequired(FALSE)` in the field definition, and then set required on the element in the widgets, based on the settings. Still need a update hook at the end, though."
# 39 UX discussion
#45 first patch from mpdonadio
#48 "Should the optional_end_date setting be moved to the field config instead of the field storage config?"
#63 should we allow start date optional
#64 'datetime_iso8601' datatype has never been set to optional in core
#76 no impact on json_api
#84 discussion around how we should display missing end date
#94 further discussion around what values to store & display if unknown end date
#139 first patch that added optional start date
#144 proposal about how to handle required indicators for optional field parts
#171 removed optional start date from patch
#193-195 decision to place setting in field not field storage
#209,210 UX review, agree to change optionality to radios
API changes
None
Data model changes
Date range end column is no longer required at database level.
| Comment | File | Size | Author |
|---|
Issue fork drupal-2794481
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mpdonadioTBH, I am not terribly keen on this, because of the ripple effects is has. Any consideration with this will need to wait until some of the refactoring we need to do gets wrapped up, the views filters get finished, and the timezone work is finalized. I really want to avoid having to do an option check in every single method (in addition to the date / date+time one we already do, which is tech debt we have to deal with).
Comment #3
skaughtit certainly is expectable that an Event will have a start time and may not have a fixed end time.. this is a normal use case.
for both UX and data validation the good old 'has end date' checkbox may get good to bring back
Comment #4
mpdonadioI guess the thing is that we now have two fields, datetime and daterange. If we make end dates optional in daterange, then we are essentially making the datetime field not needed because daterange will have all of it's features. I'm not saying we can't do this, just that this really does need to wait for other planned work to shake out first.
Comment #5
webchickMarking postponed, in that case. But I do agree that this seems like pretty essential functionality.
Comment #6
skaught#4.
I certainly get we have both fields. I think the split to datetime_range during the last phase of dev caused this. indeed there is a lot of tech dept here. re-integration of these types would be more idea in the long run.
the sort term answer for site builders is to use a conditional field state for single or end-date ready. which always makes getting views, node renders and other related queries of dates horrible cause you have to check two fields. but at least now, there is this sort term approach.
Comment #7
dkosbob commentedAs a workaround, I ended up defining a new FieldType class in a custom module that extends the DateRangeItem class, and setting Required to false there. I then used hook_field_info_alter to assign that new class to the daterange field. That allowed the end date to be optional. But since we don't actually want the end date to be left empty, I used hook_entity_presave to look for daterange fields and use the start date as the end date if the end date is left empty. In our theme, any daterange field with the same start date and end date is rendered as a single date.
The new class:
The field info alter and presave hooks, in my_module.module:
This isn't perfect and I'm sure it could be improved (please, do tell). But it seems to be working for us for the time being, until a more permanent solution is put in place.
Comment #8
cknoebel commentedEchoing Webchick in #5 with a use case I was working on when I hit this issue: I have a content type for alerts which has two levels for alerts, low and high. I know about low level alerts ahead of time and can schedule them to publish with a date range ("Elm Dr. closed for pothole repairs from 10:00 a.m. to 2:00 p.m.). In this case the date range lets me set and forget. The high level alerts come unplanned and continue for some time (I get a call that a building is on fire). In this case I have no end date because the alert is ongoing.
It would be great if the end date is optional for cases like this.
Comment #10
daften commentedThanks @dkosbob for the workaround. Just as a note, this only works for optional daterange fields, since it doesn't adapt the field widgets and the start and end date required flag are based on the field required property. Combined with browser based validation for required elements, you'd still have to fill it out.
Comment #11
gagarine commentedNo end date isn't that the end date is the same that the start date? Don't know if they will be side effect on this approach. It's what dkosbob is doing.
But yes perhaps we really want to have the information that their is no information.
Comment #13
hudri+1 on this FR, in my current project I've exactly the use case as described in #3. As a workaround I had to move to two separate date fields, but I'm missing the endtime validation and the slick UI
Comment #14
colanNow that Date Range is done, can we bring this back to life by considering #4?
Possible steps:
Comment #15
mpdonadioI'd entertain work on this now, but I consider it soft blocked on the views issues and maybe the time zone one. I also think we need to refactor the functional tests to be more manageable to avoid reroll madness. So, let's play with play with the non-test changes and get feedback on that before test coverage.
Right now, I think I am ok with two fields with some overlapping functionality.
Comment #16
kreatil commented+1
As webchick already stated: this is essential functionality. I'll try to give an example: a calendar of mixed events, some of them lasting several hours, others several days. Of again others is not known, except the door opening time, how long they will really last. So, if the end-value is a mandatory field, this can lead to incorrect information on the site, because the editor is forced to name an end time that he does not even know.
Comment #17
mpdonadioComment #18
yareckon commentedComment #20
tichris59 commentedA little workaround that works for me :
Create a php file in your module :
MODULE_NAME/src/Plugin/Field/FieldWidget/DateRangeCustomWidget.php
In formElement function I set end_value to required false
In extractFormValues i set end_value the same value as start_value if null.
Comment #21
birk commentedI've made a workaround module, we're using while this issue is being resolved: https://www.drupal.org/project/optional_end_date
So far it's only implemented in a project still under development, so it's not yet tested on a live site.
It supports null values for the end date, so the we can work with date ranges without a specific end date (the default output is the same as with start and end being identical).
Comment #22
dalra commentedI think the best solution is to make the user CHOOSE either a temporary "Present" end date (as a checkbox) OR a fixed end date.
With JavaScript, when the user clicks on the checkbox, the end date input fields are hidden and the word "Present" is shown instead.
New York - 2016.04 - Present
London - 2011.02 - 2016.04
So either way, we still have a date RANGE (not a simple date in the case the end is optional OR a date range as it is now).
With this "Present" checkbox, we can always calculate the duration of the event. We can always enter a final date instead of "Present" by unchecking the checkbox.
The word "Present" should of course be changeable and translatable.
Comment #23
jonathanshawThe #22 suggestion doesn't address what I see as one of the most common scenarios here:
describing a future event whose start date is known and whose end date is not (yet) know. 'Present' is completely inadequate in this case.
The most critical problem is: how to set things up so that content editors don't have to enter false information when they don't know the information.
Comment #24
mpdonadio#21 posting your work as a patch against 8.6, too, would help this feature more forward.
Comment #25
dalra commentedSee my comment below.
Comment #26
dalra commentedI have posted a reply which it is held for approval, so here is a better version of it:
Having the OPTION to show in the Frontend "a Date Range + a checkbox" instead of just "a Date Range" should solve the problem.
And when #2942828: Make the Date and Date Range configurable to allow MIN and MAX dates, only past or only future dates, or both is implemented, the date range will be very flexible.
My suggestion from #22 covered only one part: events which started in the past and are still happening (Present).
To also cover the other part, events with an unknown end (past unknown or future unknown), we can improve that suggestion.
In the Backend, in the date range type settings we can add an option to show Date Range + "Unknown end date" OR "Present".
If the end date was selected as Unknown, there needs to be an OPTION to show ONLY the start date in the Frontend when displaying the event's start and end dates (to hide the word Unknown).
In the Frontend, the user sees either:
Choose Start Date - Choose End Date + a checkbox "Unknown end date"
or
Choose Start Date - Choose End Date + a checkbox "Present"
When the checkbox is checked the "Choose End Date" field is hidden and replaced by the word "Present"(or "Unknown") using JavaScript.
So the "Choose End Date" field depends on the checkbox.
From what I can see, the modules for D8 which have implemented conditional fields are select_or_other, conditional_fields and business_rules.
I have tested only the last 2 and in both the checkbox selection doesn't work properly yet.
Comment #27
birk commentedThe attached patch implements what I've done in the optional_end_date module (mentioned in #21).
The idea is to optionally (checkbox added to the storage settings of the daterange field) allow
NULLvalues for theend_value.Default behavior for the formatters, when the end date is not filled, is to act as if start and end is equal (only show the start date).
It's purely functional, I've not looked at or altered any tests, it's a take on a possible solution.
Comment #28
mpdonadioGo testbot, go!
Comment #29
dalra commented@Birk
It's great to see there is progress on this issue.
Would you consider also adding an option to show the checkbox in the front-end like I suggested in #26?
It would certainly make things more simple to understand for the users who fill the data.
So, in the front-end, there will be a choice between entering an end date or clicking a checkbox (which will hide the end date input fields).
Comment #30
mpdonadioNot sure if I like this label, but that is a nit.
NW for needing test coverage. It is possible, though, that we want to refactor DateRangeFieldTest first, since that is a beast of a test class. Adding coverage for datetime, dateonly, and allday for the widgets + formatters is going to nearly double the length of that class.
Comment #31
daften commentedI've noticed that when I set the field as required, even with optional end date, the end date is required in the front-end.
I think what @dalra proposes is maybe a bridge too far, but when the end date is optional, it shouldn't be required in the front-end.
Comment #32
dalra commentedMy original proposal could be simplified (we do not keep the present day anymore) and reduced to this:
In the back-end, in the daterange options, next to the "Optional end date" checkbox, add another checkbox called "Show a checkbox in the front-end to hide the end date and show a label"
Of course, when this is checked in the back-end, the front-end user will see:
Input start date + input end date + a checkbox to hide the end date (eg: with the label "Unknown end date" or "Ongoing")
The label should be configurable in the back-end.
So in the fronted, when the user checks the "Unknown end date" checkbox, the end date input field is hidden with JavaScript and the label "Unknown end date" is shown.
If they unchecked it, the end date is shown again.
This eliminates any confusion the front-end user might have.
These 2 checkboxes (one in the back-end to show another one in the front-end) solve the problem.
If this checkbox is not implemented, it's just a bad user experience:
1) the user doesn't know if the end date is required
2) with only start date + end date, for an ongoing event, (like "Art gallery in New York": 2016.04 - still open) the user doesn't know what to do, if they should enter today's date (the wrong choice) or not to enter anything (the user is uncertain if the submission will work).
In this case the chosen label is "still open" instead of "Unknown end date".
Comment #33
mpdonadioI believe this means we will need an update path. Not adding that tag until we have a solid approach, though, so we know what we will need. But, I think that is what caused the required problem described in #31.
The patch in #27gave me a fatal on a clean install against 8.6.x when I tried adding the node:
The website encountered an unexpected error. Please try again later.Drupal\Core\Entity\EntityStorageException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'field_daterange_end_value' cannot be null: INSERT INTO {node__field_daterange} (entity_id, revision_id, bundle, delta, langcode, field_daterange_value, field_daterange_end_value) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6); Array
(
[:db_insert_placeholder_0] => 1
[:db_insert_placeholder_1] => 1
[:db_insert_placeholder_2] => page
[:db_insert_placeholder_3] => 0
[:db_insert_placeholder_4] => en
[:db_insert_placeholder_5] => 2018-02-01
[:db_insert_placeholder_6] =>
)
in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 829 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
Drupal\Core\Database\Statement->execute(Array, Array) (Line: 625) Drupal\Core\Database\Connection->query('INSERT INTO {node__field_daterange} (entity_id, revision_id, bundle, delta, langcode, field_daterange_value, field_daterange_end_value) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6)', Array, Array) (Line: 87) Drupal\Core\Database\Driver\mysql\Connection->query('INSERT INTO {node__field_daterange} (entity_id, revision_id, bundle, delta, langcode, field_daterange_value, field_daterange_end_value) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6)', Array, Array) (Line: 32) Drupal\Core\Database\Driver\mysql\Insert->execute() (Line: 1341) ... Re the approach described in #32, not sure if I like the NULL-prints-label thing or not. Any approach we take will also need a proper Usability Review and an Accessibility Review.Comment #34
dalra commentedWell, #32 can be improved.
We show another checkbox in the back-end to make the JavaScript label optional.
Some users might want to just hide the end date input field when the box is checked, without showing a label. This will show only the start date and hide the end date.
Those who need the end date label, can enable it.
We have 2 labels here:
1) next to the front-end checkbox. This could be short (1-2 words) because it's next to the checkbox.
2) one shown instead of the end date field. Here we can put a few more words to make sure the user understands
We need to make both labels configurable in the back-end.
Some users might put the same text in both, but some might want to put a synonym, to make sure the front end user gets it
Comment #35
mpdonadioReading through some of the earlier patches of #2161337: Add a Date Range field type with support for end date may shed some light on this problem, especially if some are seeing this work and other aren't (as it may appear). In that, we had problems using a dynamic schema in `DateRangeItem::propertyDefinitions()` based on the `$field_definition` settings. IIRC, this was because of when this method was invoked at different places (I would have to set some breakpoints again to be sure). I think we will have to `->setRequired(FALSE)` in the field definition, and then set required on the element in the widgets, based on the settings. Still need a update hook at the end, though.
Re #34, I am probably being dense, but I don't quite understand what is being described. A few things to keep in mind with this are
- JS can enhance the UX, but the UX and A11Y need to work properly w/o it. This is a firm core gate.
- With the datetime related widgets/formatters, we try to avoid the do-it-all scenario, and focus instead on building blocks that provide functionality, and then can be enhanced in contrib. We also don't need to do everything all at once. Optional end time has been identified as good additional functionality. I am leaning towards #32/#34 being deferred to a followup or contrib.
Comment #36
dalra commentedI have created some mockups from the patch in #27 and from my suggestions in #32 and #34.
When checkbox 3 is checked:
Comment #37
daften commented@dalra: I think most of what you suggest is overkill for a lot of use cases, and should be handled in follow-up issues. The basic premise here should be: let's make it possible to have the end date optional.
What you suggest is a huge impact on what needs to be stored, would need a lot of reviews, e.g. for accessibility. While optional end date should be do-able quicker and easier.
Comment #38
yoroy commentedComment #39
webchickWe talked about the proposal at #36 on the weekly usability meeting. There was consensus that the options provided in these mockups sound like a potentially neat contrib module like "date_time_advanced_config", but that for core, which aims for hitting the "80%" case, these sorts of options would feel like overkill.
Rationale:
- For all other Drupal fields that offer a "required" vs. "optional" (e.g. text, number, and so on), the data entry experience is to just leave the optional field blank and then it won't get printed upon display. Other fields do have the ability to define a default value, but not a "what to print here if someone leaves it blank" value, and that seems odd to add to this one field and not others.
- This also seems to match what in a quick check Google Calendar, Meetup, Facebook Events, iCal, etc. do. Those services don't actually let you pick an optional end date... they default to the current one, and if the from + to date match, they simply print the from date (this seems like very sensible behaviour for Drupal as well). There are no options to choose customized text to show instead; that would complicate the data entry quite significantly.
So, given the other Drupal fields and these other popular event management services will demonstrate generally expected behaviour, and the closer we can match them, the better off we'll be, I'm inclined to agree with @daften on this proposal being out of scope. But once again, feel free to create a contributed module that offers these options, if you feel people would benefit.
Comment #40
dalra commented@daften
If the end date is optional, the only thing that is stored instead of it is NULL.
So there's no impact here.
In the mockups, I only suggested a few very simple things:
1) Show a simple checkbox in the front-end to improve usability and user experience.
2) Give a name (a label) to that checkbox. Don't show a box without a name.
3) Have an option to show a label when the end date is hidden. It's very useful also to the people who use screen readers.
4) When you want to show in the frontend a date range which already has a NULL end date, have an option to show the label from 3) instead of NULL.
I really don't think that an optional label and (1 checkbox plus its name) would require much effort in terms of coding.
If you have any suggestions please share them.
However, as it is now, with only the patch from #27, won't pass any usability or use experience tests.
I gave an example in #32.
Comment #41
dalra commented@webchick
I saw your reply only after my previous post.
Please consider the events that have started in the past which do not yet have an end date (are still happening).
In this case, the users might enter the current day as the end date. That would be totally wrong, because it would provide a end date even though there is none yet.
Eg: How long have you been living in that city?
From 2016.10 to:
a) (Enter today's date - wrong choice - OR don't enter anything). This is confusing, leaves the user guessing what to do.
b) a checkbox: I'm still living here (of course the date is saved as NULL and we just show a label for NULL)
Comment #42
daften commented@dalra, if there isn't much effort in terms of coding, I'd advice to make a patch :)
The coding part is often not the most difficult part, it's the usability and accessibility that are the difficult points sometimes. This also applies to the editor interface. Having the basic functionality of an optional end date (as it was there in D7) will be difficult enough. I'm not saying, and neither is @webchick, that your suggestions are invalid. I'd just advice you to put them in a different (follow-up) issue. This would help keep the basic discussion here clean and ONLY about optional end dates.
Comment #43
jonathanshawWhat Google calendar also does update the end date every time you update the start date, to keep the offset from the start date constant. This makes editing dates much less annoying.
Perhaps we don't need to allow the end date to be null, maybe it's OK to
1) simply default the initial end date to equal the start date (which we probably do already)
2) change the end date when the start date is changed to preserve the relationship
3) make the formatters show just the start date when the end date equals the start date
This makes it easy for a sitebuilder to setup a fairly good editorial experience.
Setting the end date to equal the start date seems an acceptable way of communicating "the idea of an end date doesn't apply here". Allowing NULL would be a way of allowing sitebuilders to say "this could have an end date but I don't know it"; but that doesn't seem like an 80% use case.
There's no doubt that if there was a situation where end dates were frequently not needed for a certain date field, it would be a better UX to have a checkbox like @dalra describes. But it's very easy to implement that in a contrib widget. The simplest possible version of @dalra's suggestion, which might be worth considering in core is to have a widget setting "Don't show end date input initially"; if checked it would hide the end date input using only css unless an "Add end date" link was toggled. But anyway, definitely this kind of UX refinement can definitely be postponed to a separate issue.
Comment #44
mpdonadio#43, (1) and (2) are in #2863444: Discourage/make impossible to select a "to" date that is before the "from" date, which mostly works, but needs tests. (3) should be the default behavior in core already (see DateTimeRangeTrait::viewElements() and I know we have coverage in DateRangeFieldTest for this).
Comment #45
mpdonadioHow about something like this? We still need something that works w/o JS, so #2863444: Discourage/make impossible to select a "to" date that is before the "from" date can only be an enhancement, not a solution.
Comment #46
mpdonadioIt is also worth mentioning that the only correct way to test this patch is to apply it it 8.6.x, then do a site install. Without the update path, the database schema / field definition will be wonky.
Comment #47
birk commentedAdded some extra logic to the #45 patch, that will require the end date, if optional_end_date is not selected.
Should the optional_end_date setting be moved to the field config instead of the field storage config, since it doesn't alter the storage anymore?
Comment #48
mpdonadioI'm included to keep it with storage so that the `hasData` check prevents it from being changed. Worried that if we get NULL values in storage and someone changes optional => FALSE, it will cause weirdness.
Comment #49
birk commented#48 Fair point.
Added an update hook, that changes the end_value column of existing fields.
Comment #50
birk commentedAfter the update the "Status report" page had an error with "Mismatched entity and/or field definitions" on the fields updated.
Instead of changing the schema directly (like #49), this patch simply saves the field definition again, and because the definition is updated the database schema is updated as well.
I'm not sure this is the correct way of handling this, I've been looking at EntityDefinitionUpdateManager::applyUpdates(), but it updates everything that is mismatched.
I haven't been able to find a best practice for updating existing fields in a hook_update_N, The one I've used in this patch seems to be the least intrusive, that wont result in a mismatch error, but maybe someone can chip in if there's something obvious I've missed.
Comment #51
mpdonadioThis is looking nice.
There is an update hook in #2716891: DateTimeIso8601::setDateTime() vs. DateTimeItem::schema(): (at least) one of them is broken, but that one is really complicated and I haven't tried to simplify it yet. There aren't a lot of examples in core.
I think the next step would be an update path test to check the assumptions in the update hook. That will require a fixture. I would start with the fixture in #2716891: DateTimeIso8601::setDateTime() vs. DateTimeItem::schema(): (at least) one of them is broken, and then add three daterange fields (date+time, date-only, allday) and a few nodes, and add some assertions. If we coordinate the fixture between the two issues, it will minimize having to add them to core and whichever patch lands first will be able to use the other.
Then that should settle the mechanics of the change, and we can focus on the UX.
Comment #52
birk commentedIt turned out simply saving the StorageConfig didn't update the database (I must have been testing it wrong when I made it).
So I've updated the update hook to use the changeField() function again. And then manually update the storage_schema.
I've used the fixture from #2716891 as a base, and added 3 daterange fields to the node (allday, date and datetime). I've also added a daterange field a taxonomy_term to test not revisionable fields as well.
It's my first ever test, so it took me a while figuring out some of the magic, and I might very well have done something the "wrong way". Please point me in the right direction, if the test is a lackluster or otherwise in bad form.
Comment #53
birk commentedFixed an issue, where no start or end date was filled (and the field wasn't required), but a form error was called anyway.
I've also fixed the code style, so it follows the Drupal standard.
Comment #54
skaughtComment #55
matsbla commentedI wonder if this option could be configured for each content type, instead of in the field setting?
Then you can make the end date optional for some content types, and mandatory for others.
Comment #56
runeasgar commentedAs far as I know, field settings are per-field, by convention. So, I'm going to assume this needs to be tested.
This value should not be null..curl -l https://www.drupal.org/files/issues/2018-05-03/2794481-53.patch | git apply -v. Received some errors I don't fully understand:Given that this reads like a non-functional issue, testing the patch anyway
drush crdoesn't work with SQLite. Actually.. wee.. looks like clearing it through the UI also causes problems (forever spinning). Maybe quick-start isn't a good way to do core issue testing. Restarted via Ctrl+C and re-running quick-start to turn the PHP server back on. [/tangent]Not marking this as RTBC, since the patch doesn't seem to work, and also looks like there might be whitespace issues. Re-queing latest patch for testing, and marking as "Needs reroll" because I think that's what needs to happen here? Sorry in advance if I'm wrong.
btw this issue has a ton of tags on it.. are they all still applicable?
Comment #57
birk commentedI've tested the patch on a normal (not quick-start) installation, and it seems to work. It seems you're missing a few steps in the reproduction, I've done the following:
/update.phpordrush up.The patch warnings are all caused by the
core/modules/datetime/tests/fixtures/update/dump.php.gzfile, but the code is applied correcly. I don't know how to fix these warnings, should I create the patch in a different way?Comment #58
mpdonadioSorry I have been AWOL. Life got in the way. Few quick things.
This still needs tests. I am only seeing an update test in the patch. At a minimum we need updates in DateRangeItemTest and DateRangeFieldTest, but considering the later is 1300+ lines of mess, we may want to figure out some refactoring in a side issue. I need to review the status of the constraints and some of the other REST issues to see where we land.
This needs manual testing, both on a clean install (to test the patch itself) and on an existing install w/ data to test the update path.
We can ignore coding issues in the fixture.
Given that the usability of the widgets was a bug problem with getting this in core, it will need a proper Usability Review by that team.
Comment #59
runeasgar commented@Birk I missed the update.php part! Thanks for pointing that out.
Comment #60
birk commentedI've moved the end date validation out of the
DateRangeWidgetBase::validateStartEnd()and intoDateRangeItem::getConstraints()instead (which seems like a better place for this anyway). So the entityValidateAndSave function can be used in the test.These are the first tests I've written, and it seems scarce, but I lack the experience of figuring out how much and exactly what to test, I've included what I felt meaningful.
Should we wait with the DateRangeFieldTest till refactoring is decided?
Comment #61
skaughttrigger test
Comment #63
roi commentedI want to emphasize that most of the comments here relate to END DATE, but the solution should be symmetrical, meaning the user might want to fill ONLY the end date and leave the start date empty.
for example
Describe the period when people didn't have vaccination for smallpox ("always" until 1796)
Comment #64
jrockowitz commentedI just want to give everyone the heads up that the 'datetime_iso8601' datatype has never been set to optional in core. I discovered this because someone created #3017945: [upstream] Field types with a required property *and* an optional @DataType=datetime_iso8601 property trigger fatal error in DateTimeNormalizer when optional property is empty.
We might see some minor regressions when we change the date range field's start and end date to optional. I don't this is a big deal.
The JSON API might have to allow for an optional 'datetime_iso8601' datatype.
Comment #65
skaught#63
This is in interesting use case Although it has as much todo with how that field label is phrased and how that date is then interpreted when displayed. I imagine your content type of 'medicines' would have a 'date invented'. Then referencing it to say 'before then there was none' in a regular sentence is a normal human expression of that timeline. In so, your 'date invented' field would never have an end date -- unless mankind lost the formula (:
Comment #66
s-jack commented#63
+1
I feel the necessity that blank spaces are possible on the start date as well.
There are times when you do not want to display the start date intentionally and may not know for a long time like history.
The end date is also similar in thinking abstractly.
Regarding the concept of start and end, we have similar concerns about time.
I feel that it is necessary to satisfy the four conditions.
single
Start only
End only
period
These repetitions(Multivalue)
It is inconvenient to select the date, date and time in the field setting.
I want to use multivalued with no time and time.
I appreciate your discussion and development!
Comment #67
pfenriquez commentedFirst, thank you for the great work.
Concerning path #60 I noticed two errors.
1 - it creates a core folder in the Drupal core folder, containing a modules folder. If I am not wrong the changes should be made exclusively in the modules folder in the original Core folder.
2 - I had to create a second patch in order to see the end date empty in the node edit form when optional and empty. With patch #60 the end date is set on start date.
I had to change from
if ($items[$delta]->end_date)to
if ($items[$delta]->end_date && $items[$delta]->start_date != $items[$delta]->end_date)on line 44 in DateRangeWidgetBase.php
Comment #68
benjifisher@Penef:
I am not sure about your second point, but I think I can explain the first one.
This patch does not add the
code/core/subdirectory. You can confirm that by checking out a fresh copy of Drupal's git repository and applying the patch with eithergit apply -v path/to/2794481-60.patchorpatch -p1 < path/to/2794481-60.patch.I am guessing that you are using composer to manage your site, and you are running into a bug with older versions of the composer patches plugin (
cweagans/composer-patches). Try upgrading that to the latest version (currently 1.6.5) and update yourcomposer.jsonas in the current version of drupal-composer/drupal-project.References:
Comment #69
pfenriquez commented@benjifisher
It is the first time I have this kind of problem (even on recent patches), but you are right I am using composer to apply the patch.
cweagans/composer-patches is already at 1.6.5 on my installation, but the problem persists.
It is eventually an error in the way I applied the patch, but as I use the same way on various projects without encountering this error, I was guessing it might be the patch.
Thank you for the answer.
Second point is still valid (on my side).
Best regards
Comment #70
benjifisher@Penef:
Please see the second link I quoted. The latest version of cweagans/composer-patches (1.6.5) adds a new option, but if your configuration does not use that option, then you will still apply patches with the wrong patch level.
As I said in #68,
Specifically,
Comment #72
jian he commentedThe patch already have automated tests, update path, and update path tests.
Comment #73
gorkagr commentedHi!
With the comment in #70, patch is applied properly.
Related with the patch itself, in #52/#53 it was added a new file (core/modules/datetime/tests/fixtures/update/dump.php.gz) and is there.
Is that file neccessary? It seems to work without the file being there.
Comment #74
unstatu commented@gorkagr this file is used for preparing the testing environment (the database) and having a controlled scenario for executing the tests.
Tested #60 and worked on 8.7. Thanks!
Comment #75
mpdonadioNeds to be in datetime_range.
Need to update to an 880X hook.
We either needs to resolve this @todo or remove the comment.
Ditto, or w/ a followup (there may be an issue already to remove these.)
Also, there are item test and update path tests, but we also need formatters tests, and probably widget tests.
Also going to ping @WimLeers to see if there is REST impact here.
Comment #76
wim leersThe impact on the
restandjsonapimodules is simple: they will automatically respect the optionality and validation constraint that this patch is introducing. It'd be nice to have explicit test coverage for them, but that's definitely not required.Furthermore, this is a widening of what is permissible, not a narrowing, so no existing API clients could possibly be negatively impacted by this.
The only way they could be negatively impacted is if they were performing a request whose body did not contain an end date, which would have triggered a validation error, and the client is checking for that particular error string: this patch does not guarantee through test coverage that the error message is exactly the same before and after. But that's such a remote edge case that I would not expect this patch to explicitly test that.
Comment #77
mpdonadioThanks @WimLeers. I added a followup to enhance the REST test coverage to account for this new feature.
Comment #79
colanThis still needs to be set back to NW because some tests are missing, but let's trigger the testbot first to see if the changes break anything.
From #75:
1. Moved.
2. Updated.
3. Removed, but please post another patch if anyone knows the reason. I couldn't find a reason for this anywhere here.
4. Comment removed, and I replaced
REQUEST_TIMEwith\Drupal::time()->getRequestTime()as per Time Service Added and REQUEST_TIME deprecated. We're in a static method here so I couldn't use dependency injection. I leftmt_rand()as-is because we're not running in a security context.Comment #81
colanThis should fix the test failures.
Comment #83
colanLooks like we're running into Added configurable match limit to the entity autocomplete matcher. Anyone know where that stuff gets set?
Comment #84
colanI added the above things to the list of remaining tasks in the IS.
Some things I discovered while playing around with this on the front-end, which I also added to the list:
3.
This is a bit wacky as we're losing entered data. If we don't want to accept a missing start date, don't allow form submission. Instead, show an error. However, we could also allow this and actually save the data. I recommend doing this instead. This was mentioned earlier. Just as we may not know the end date, we may also not yet know the start date.
4.
This can best be illustrated with an example. If we have a "Drupal Week" field, but don't know the end date yet, the start date should be displayed with some indication that no end date was set. Displaying the start date on its own doesn't make much sense. Basically, I'm disagreeing with #27:
This is too unclear. If that's what we want to do, we should show start date - start date, but it doesn't work in all contexts. There needs to be a way to specify that data is missing, and should be added at some point. We could show the separator after the start date and making this hyphen display configurable: "Display separator with missing end date?". Or we could have the opposite question: "Assume a missing end date is the same as the start date?"
Probably the simplest thing would be to forget about config, and just add the separator before or after (depending on which subfield is missing, start or end date). This will work in both cases. If users want a missing date to really be the same date as the other subfield, they should specify this explicitly, and fill this in.
Comment #85
colanComment #86
dpiBlocks Recurring Dates Field: #2915298: [PP-1] Allow end date to be optional (date_recur)
Comment #87
xmacinfoRetested #60 to see if we have a patch passing for 8.8.
Comment #88
colan#87: Why #60? Why not the latest one?
Comment #89
xmacinfo@colan I am using #60 internally for our project. I was not sure about #87 since it is displayed in red.
Comment #90
j-lee@colan I think the best way for point 4 at #84 is to make an unknown end date indicator optional. (see #36)
We use the Date range field to display the dates for trade shows. Mostly they are longer than one day, but sometimes they are only one day. Our content authors don't want to add an end date in this case (all independent of each other). So I think the #27 hint is a common use case which is done with the current patch from #81.
Comment #91
kengilb commentedRe-rolling #81 with the date field's timezone support from:
https://www.drupal.org/project/drupal/issues/2632040 #273
This is probably specific to my use case but thought I'd share if others are looking to combine the two.
Comment #92
xmacinfoComment #94
ckaotikRegarding some of the thoughts from comment #84:
3. I agree, missing start dates are a very valid use case and since we're already touching all the relevant code places, we should add that.
For field configuration, we could add a second checkbox ("Start date is optional").
The field formatters'
viewElementscould then simply check forif ($item->isEmpty()) {continue;}, withDateRangeItem::isEmptyreturning TRUE based on the "optional parts" settings.4. I also agree that there is a major difference between "missing data" and "implicitly the same".
Core date widgets currently have the assumption that "empty value" means "now". If we made this "Empty value behavior" configurable, we could include the options "Current date/time" (default), "Same as other value" (as suggested in #27) or "Leave empty" (as suggested in #84). That would allow for appropriate data processing (i.e. filling the start/end date or leaving it as NULL).
I'd suggest this configuration either on the field storage settings, or on the widget settings. In my experience, editors always have some kind of training for how to use their site - different site owners expect different logics that also affect other parts of the sitebuilding process (e.g. Views). Thus, I think this setting does not need to be handed to the editor (suggested in #36) but to the sitebuilder, which hopefully helps reduce the complexity.
For the indicator when outputting the date on the front end, we could leave this up to the theme, by outputting only the appropriate element on missing date parts: Only fill the
start_datekey if the end date is missing, only theend_dateif the start date is missing, orstart_date,end_dateandseparatorif both are present. That way, a template can easily check which data is present, and do things like add prefixes (e.g. "until {{ end_date }}", "since {{ start_date }}") in certain cases.This also keeps the meaning (and thus description) of the separator formatter setting intact: "The string to separate the start and end dates".
Additional thoughts:
5. How do Views filters deal with NULL values in start/end date field values?
Comment #95
colanComment #97
herved commentedUpdating the patch from #81 to fix the test failure.
The trigger_error() there is called from
system_entity_form_display_presave()when the database updates are executed fromDateRangeUpdateTest::testEndValueNullI believe the only way to fix this is simply to run db updates on the dump.
According to the schema that dump was produced before 09/02/2018.
So I ran all database updates from the current 8.8.x HEAD (commit 154038f1401583a30e0ea7d9c19db02f37b10943)
Is this dump truly necessary? Any other way we can test this without such dump?
I'm attaching the updated dump as well.
Comment #98
ravi.shankar commentedHere I have just fixed the failed test of patch #97 for Drupal 9.1.x.
Comment #99
john.nie commentedWhy not allow start date and end date optional ?
It's a new patch for this.
Comment #101
whiz11 commentedI have successfully applied the patch but in my view, the end date is not shown
#Updated: I have removed the date field from the view and added another with another id and it works now
Comment #102
janmejaig commentedI have checked the above issue and applied the latest patch for the same but still issue is not resolved. Please look into the issue .
Comment #103
danharper commentedPatch in #98 tested and working although if no end date is set then the date is not rendered in views.
Need to be able to render the each part of the date in views so that the following is possible.
01/01/2001 - current
It looks like if either date is null then views treats the whole field as null.
Comment #104
simeRe-rolling #99 for whitespace fixes and wondering if that composer related test fail will repeat.
Comment #106
simeThe patch from #99 is suggesting that both the start date and the end date could be optional (although this is only partially implemented in the patch).
So to be clear on the logic:
My opinion is this is the most flexible and generic (80%) option that covers the most cases, and makes the validation rules more consistent.
Comment #107
simeThe patch at #98 reflects the dominant discussion on the issue: that the end date can be marked optional. It appears to work OK in my manual testing so far.
Comment #108
simeRe #99, I thought that being able to make
endORstartoptional could have cleaner logic (and generally make the field more flexible) but as I tried coding this I found the logic (and UX) was still awkward to cover the combinations of field/start/end dates being required. I'm going to review #98 next.Comment #109
simeRe-rolled #98 to fix whitespace changes.
Everything seems to work as designed. Having an optional end date highlights that there is no easy way to clear an existing date value in the editing interface.
I think a lot of limitations of the field display (not being able to do custom things like
- currentwhen end dates are missing, for example) could be solved by adding a special theme twig so that start/separator/end can be controlled. I think that would be really practical here.(Note that you can control things in views by using conditional twig to check if the end value exists and conditionally printing, so the limitation is mostly in the node display, in my opinion.)
Comment #110
jonathanshawDoes this potentially address this:
Comment #111
simeAdding a theme twig would give a lot more flexibility in the output, but no it doesn't solve the limitation whereby some people might want an "optional start date" in the editing UI. I agree with @webchick at #39 that there's a happy medium.
Comment #112
john.nie commentedComment #114
ccjjmartin commentedThe patch in #109 contains a db dump of test fixtures so I don't recommend using it. The patch in #99 doesn't do what it says it is supposed to do (add optional start date, I didn't see a checkbox for it on the field settings). I am testing #98 and so far things are working as expected after selecting the "optional end date" checkbox on the field settings.
As a general note, for anyone migrating a datetime range field from D7 to D8/9 you may think they need this patch but it after configuring the end date to import values properly you may find that you don't need it. The key for me was that the value2 in D7 maps to end_value in D8/9. Here is my config:
I can say though that when I didn't have end_value set properly the patch in #98 worked just fine.
Comment #115
douggreen commentedIn the formatter, when checking if we should display the end date, I would like check the formatted value, and not just the time. For example, if the formatter just has the date and hour, and the start and end date are in the same hour but have a different minutes/second, IMO we shouldn't show the end date. ... but maybe this change should be another issue (or just a contrib module formatter), as this is how core currently does it.Edit: It would be nice to work a similar change from #2823847: DateRange formatters should compare rendered dates instead of raw timestamps into this patch. The two patches conflicts.
Comment #116
stella commentedAttached is a rerolled version of the patch from #109 without the db dump file and the test (src/Functional/Update/DateRangeUpdateTest.php) which relies on it. I'm not sure of the best way to approach amending/replacing that test however.
Comment #118
nikitagupta commentedComment #119
randell commented#118 tested working for Drupal 9.1.6.
Comment #120
renatog commentedIn the method: "getConstraints" we can use early return approach with
The function will be:
It's better because reduce one huge "if" conditional, and reduces the Hadouken effect in the code
Comment #121
xmacinfoWhat is a “Hadouken effect”? 🙂
Comment #122
solideogloria commentedI'm guessing it refers to when the indentation level gets really far over. It's better to return early, rather than have a bunch of nested conditionals.
Comment #123
colanFor the curious, it's called a guard (which "remov[es] one level of nesting and resulting in flatter code"), and Uncle Bob is a fan as per Clean Code. (Everybody here has read that book, right? ;)
It makes the code much "cleaner" as there's less nesting, which should be avoided. So 👍 from me.
Comment #124
renatog commented@xmacinfo #122 and #123 are right about that.
Hadouken effect is only an informal/funny way to say it
Comment #125
renatog commentedPlease, disconsider it
Comment #126
renatog commentedFollowing the new patch with this improvement
Comment #127
bbombachiniThe patch works for me!
Comment #128
petr illekThe patch in #126 is working fine for me so far. I had to remove the field and add it again in order to make it work.
Comment #129
renatog commentedso according to #127 and #128 let's update the status
Comment #130
jonathanshawPer #75 we need formatter and update tests, and probably widget tests. There was an update test, but it was removed in #116.
Comment #131
colanI'm not seeing any of the other remaining tasks crossed out either.
Comment #132
steinmb commented@Petr Illek - Did you run run "drush updatedb" after applying the patch? There is a update task that should make sure you do not have to nuke the field to make core date range work.
Comment #133
lisotton commentedJust a small remark: in Drupal 7, when the End Date was optional and tried to fill the End Date field, but left the Start Date empty, it was showing a validation error: "A 'Start date' date is required if an 'end date' is supplied for field %field #%delta.".
Now the behavior implemented in the patch is to simply ignore the End Date value if the Start Date was not supplied. I guess it would be nice to have an error message for the new implementation as well.
Comment #134
danharper commentedJust testing the latest patch and when rendering a date field with no end date in views it doesn't render at all because it thinks it's empty.
Comment #135
webcultist commentedJust tried the patch together with commerce and got the following error message when tried to add something to cart with an optional end date.
Not sure if this is the right place, but thought it's maybe helpful.
Comment #136
solideogloria commentedMinor grammar fix.
Comment #139
barig commentedHi everyone !
I updated the patch to allow having an end_date without a start_date ("value" is now nullable).
I also added a test to test that the case I'm introducing (having start_date=NULL and end_date=XXXXX) passes the tests.
The patch has been rolled from 9.3.x.
Best regards,
Barig
Comment #140
barig commentedHi again,
I rerolled the patch to squash the commits.
Thanks !
Comment #141
aaronmchaleAll new feature development should be targeted at the latest core branch, that being 10.0.x.
Comment #142
ravi.shankar commentedAddressed Drupal CS issues of patch #140.
Comment #143
junaidpv#126 worked for a site running Drupal 9.4.8
Comment #144
gugalamaciek commentedCurrent implementation generates:
So, it provides "(optional)" suffix to end date label. But... we have asterix (*) as a way to point if something is optional or not. I'd like to propose update for #142 to generate this UI:
If end date is optional, no asterix on it and wrapper (as not all fields inside wrapper are required).
If end date is required as well, then this UI:
and if all is optional:
Comment #145
xmacinfoI like the usage of asterisks (*) in #144.
Comment #146
pyrello commented+1 for proposal in #144
Comment #147
dalra commentedThe current implementation is confusing.
The only visual difference between the required date and the optional date is the red asterisk.
This asterisk is just missing if the date is optional and a normal user has no visual indication that the date is optional.
As I said in #26 and #36 a better solution is to also put a checkbox after the optional end date to visually hide it and make it clear to everyone that the end date is optional.
This is how they did it on other websites and it makes sense.
Comment #148
maxilein commentedAt first sight: Why would I want the extra effort of a checking box?!
The red asterisk is perfectly sufficient.
I like #144 because of the simplicity. It should be the default.
I can understand that there are use cases for #36. They are just too complex for the default.
Comment #149
aaronmchale"(optional)" is not a pattern we use elsewhere, we use the asterisk to denote when a field is required, and that is a pattern which is consistent across applications.
We should not attempt to introduce a new pattern for that in this issue.
Comment #150
rgpublic+1 for #144 also from me. Let's keep this simple. A checkbox needs to be clicked each and every time when someone is filling out the form - quite annoying. It doesn't remove clutter though as the input field is hidden but there would be a checkbox instead. We also don't have such a checkbox for other optional fields (e.g. Drupal commerce's "address line 2" on billing addresses etc.) which would be inconsistent.
If people are anxious about users not noticing that the second field is optional, they can always customize and add a description, specific placeholder, colors etc. to make it clearer.
Comment #151
dalra commentedThe checkbox is useful in case you want your site's average users to correctly enter a date range for an event that is still happening and will continue to happen after today.
In the back-end there can be an option which shows or hides the front-end checkbox.
Example:
- With the checkbox the uses select the correct end date (none):
I am a student from [2021/09/15] - [x] Present
When the front-end user clicks the [x] Present checkbox, the the end date [Y/m/d] is hidden
- Without the checkbox most people will select the current date as the end date, which is wrong.
I am a student from [2021/09/15] - [2022/12/21]
They will be confused:
"What end date should I select here? I am still a student.
Do I select TODAY as the current end? That doesn't seem right... I will be a student TOMORROW as well.
Do I leave it empty? Maybe... BUT what if it shows an error?"
Every other website solves this confusion by using a checkbox for No end date (ex: the Present).
Again, this front-end checkbox can be made OPTIONAL (hidden) from the back-end.
Comment #152
maxilein commentedLet's keep this simple. When the end date is made optional the scope of this issue is done.
And it is according to all Drupal UI standards.
And we can finally finalize this important functionality.
#151 etc could be moved to a separate issue.
Comment #153
_utsavsharma commentedFixed CCF for #144.
Please review.
Comment #154
jonathanshawThis is right. Getting a complex issue like this fixed requires a tight scope. #151 is a useful consideration, but better to address in a follow-up issue I suggest.
Comment #155
ameymudras commentedThe above patch #153 replaces the instance of REQUEST_TIME but strangely the CCF is still failing.
Comment #156
mandclu commentedUpdating to target the 10.1.x branch.
Comment #162
kunal.sachdev commentedComment #163
kunal.sachdev commentedComment #164
kunal.sachdev commentedComment #165
srishtiiee commentedLooks good! Left a minor feedback. Also, this most probably requires a change record.
Comment #166
kunal.sachdev commentedAddressed review and created CR.
Comment #167
smustgrave commentedHiding files as fix is in MR.
Left some small comments.
Comment #168
kunal.sachdev commentedComment #169
srishtiiee commentedComment #170
lauriiiPosted a review in the MR
Comment #171
kunal.sachdev commentedComment #172
smustgrave commentedReviewing the remaining tasks and was only able to say that 1 is done.
Since this isn't using a formatter anymore first bullet may not be needed but could someone familar with the issue confirm?
Same for 2nd bullet
If not needed "Needs test" tag probably can be removed.
Comment #173
kunal.sachdev commentedYes, I think the 1st and 2nd bullets in remaining tasks are not needed and about the last bullet in remaining tasks I don't think we have to do it in this issue because the current behaviour in the MR is to show only start date when end date is missing which I think is fine for this issue.
Comment #174
smustgrave commentedApplied the MR on a Standard profile install of 11.x
Added a range field to the Basic page content type.
Checking "Make End date optional"
Created a Basic page and didn't set an end date. Node saved without issue
Went back to the settings unchecked "Make End date optional"
Went back to my Basic page and now I'm required.
Ran drush updb and post_update and install hook ran without issue.
How come the setting is under the field storage though and not a form formatter setting though? Won't this mean editors can't reuse this field in 2 places where 1 should have optional end date and the other not?
Also think issue summary could use some work.
may be having a case of the Mondays but was a validation added?
Also there are some UI changes that are missing from the issue summary.
Comment #175
kunal.sachdev commentedComment #176
kunal.sachdev commentedComment #177
kunal.sachdev commentedI am going to work on shifting the setting to field settings so that this field can be reused in 2 places where 1 should have optional end date and the other not. I am also going to work on adding the validation constraint.
Comment #178
smustgrave commentedOnly if you think that is best approach. Wasn’t saying that it was needed more general observation/discussion
Comment #179
jonathanshawAdded history of discussion to IS to enable easier reviewing of the discussion so far.
Comment #180
jonathanshawThe key questions
5 key questions have recurred again and again over the life of this issue:
1. Is the start date optional too?
2. What value is stored in the end date property if it is left empty in the widget?
3. Does the optional_end_date setting live in the field config or field storage config?
4. How are optional and non-optional properties distinguished in the widget?
5. How are missing end dates displayed in the formatter?
I have added these to the IS. The answer in the current MR is:
1. Is the start date optional too? NO
2. What value is stored in the end date property if it is left empty in the widget? NOT SURE
3. Does the optional_end_date setting live in the field config or field storage config? STORAGE
4. How are optional and non-optional properties distinguished in the widget? NOT SURE
5. How are missing end dates displayed in the formatter? ONLY START DATE IS SHOWN
I think we need to be careful to keep track of our answers to these important questions in the IS, even as we work on the details of patches.
Kunal
@kunal.sachdev some feedback/requests for you:
A. Please could you tell us the answer for the questions I've answered "NOT SURE" above
B. In #48 a subsystem maintainer suggested to keep the setting in the field storage config
C. Please post a screenshot of the widget so we can see that the "required" indicators follow th suggestion made in #144
Tests
Lastly, I believe that even though we are not making large changes to the formatter and widget, we still need to explicitly test that they work with missing end dates. Therefore we need both formatter and widget tests.
Scope
If this issue is to ever get committed, realistically we need to keep the scope tight and defer to follow-ups anything we can. Therefore I suggest:
- Optional start date. This is a valid use case, but let's open a follow-up issue for it.
- Customising display of missing end date. This is a valid use case, but let's open a follow-up issue for it. Per product manager's usability review in #39, core should not offer complex options here and it is fine to just display start date if the end date is missing.
Therefore I think the current MR is correctly scoped.
Comment #181
kunal.sachdev commentedAnswering some of the questions asked in #180 :
In #48 we have suggestion to keep the setting in the field storage config but I do agree with #174 that if this setting is kept in the field storage config editors can't reuse this field in 2 places where 1 should have optional end date and the other not that's why I am going for shifting the setting to field settings.
Screenshot of the widget if the end date is optional:

Screenshot of the widget if the end date is required:

Comment #182
solideogloria commentedThe answer can only be
NULL, or to use a separate Boolean likeend_date_is_all_day.This issue happened before, in the Date module for 7.x. See #3202962: Expand field specification with new element for "all day". Using a "magic value", such as storing the date with a certain time to indicate that it's an all-day value, was a very bad approach that led to multiple issues. It eventually was rewritten in 7.x-3.x, but bugs linger in the 7.x-2.x branch and it's hard for sites to update or clean their data that was messed up.
Comment #183
jonathanshaw#35 discusses some specific problems with putting the setting on the field config not the field storage config.
The screenshots in #181 match the consensus suggestion in #144, so that's good.
Comment #184
kunal.sachdev commentedFor now I am keeping the setting in field storage config and I think we can decide on shifting the setting to field config in another follow-up.
Comment #185
kunal.sachdev commentedCreated follow-ups:
Comment #186
feyp commented@kunal.sachdev Thanks for creating the follow-ups. Can you please set the status of the follow-ups to Postponed and post a comment that they are postponed on this issue when you change the status? You can also add this issue as a parent issue or as a related issue. I don't think it makes sense for someone to work on these issues until this issue is fixed.
Also, I think it might be a good idea to list the follow-up issues somewhere in the issue summary, because this issue is pretty long and takes some time to read through, so a good issue summary that has all the relevant information is even more important for this issue to make it easy for core committers and other contributors new to the issue.
The issue summary also lists a remaining task (2.) that is not marked done yet. Can you please update the IS with the current approach in your implementation and/or with a reference to the follow-up you created, so that it is clear that the task is either done or out of scope?
W/r/t the last follow-up, a subsystem maintainer mentioned in #48 that the setting should be kept in field storage. Unless there is compelling evidence that the reasons given by them are maybe outdated in the meantime (they commented 5 years ago, so it might no longer be true due to some other changes in core), I think we should follow their advice and keep the setting in storage. If we think the setting should be in the field settings, I don't think we should have a follow-up, but I think we should do it in this issue. It doesn't make much sense to introduce a new setting now and then shift that from storage to field settings later. We could then use a field setting right from the start.
Comment #187
kunal.sachdev commentedComment #188
kunal.sachdev commentedComment #189
kunal.sachdev commentedComment #190
kunal.sachdev commentedClosed #3395103: Shift the optional_end_date setting from field storage config and added new remaining task to decide if we want to shift the optional_end_date from field storage config or not.
Comment #191
jonathanshawThanks kunal. Added remaining tests needed to IS
Comment #192
kunal.sachdev commentedYes the validation constraint is added in
\Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem::getConstraintsand test is also added for that\Drupal\Tests\datetime_range\Functional\EntityResource\EntityTest\EntityTestDateRangeTest. I think I am going to remove that constraint and add a separate constraint class and its validator because I think it's the more correct way to do it.Comment #193
kunal.sachdev commentedDiscussed about some points with @lauriii and @tim.plunkett in scrum :
\Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem::getConstraintsand decided to keep it that way.Comment #194
lauriiiJust reading through the MR now in detail; it looks like the MR is not actually configuring whether the property is required or not in the schema level. It looks like there were some challenges with this approach in #33. I did find
\Drupal\Core\Field\Plugin\Field\FieldType\StringItemBase::propertyDefinitionswhich configures the property based on the field definition, so I wonder if that's worth trying.However, if we are not configuring this on the property level, but instead in the validation constraints, then this could be a field config setting, because it could be applied according to the field config. We have pre-existing examples of this like
\Drupal\Core\Field\Plugin\Field\FieldType\NumericItemBase::getConstraints.I do think @tim.plunkett raised a compelling argument that in some cases you may want this field to have different behavior in different bundles, which would support the idea of configuring this in the field config. So the question then becomes, is it acceptable for the
end_valueproperty to be always optional, for the requirement to be enforced in validation constraints depending on the field config setting?Comment #195
larowlanYes - I agree with @lauriii and @tim.plunkett, making this vary per field config rather than storage if there's no DB schema change feels like a good approach.
Comment #196
kunal.sachdev commentedoptional_end_date setting is moved to the field config and hence closed #3395103: Shift the optional_end_date setting from field storage config.
Comment #197
kunal.sachdev commentedComment #198
jonathanshawSo we have consensus on the solution, and the MR is complete.
I am not convinced a further usability review is needed, so I think this can be RTBC after code review of recent changes.
Comment #199
narendrarLooks good to me except some suggestions and one question.
Comment #200
kunal.sachdev commentedComment #201
smustgrave commented@kunal.sachdev believe as the starter of the MR you can close the threads just FYI.
Nice to see it moved out of the storage setting.
Tested as before
Created a range field with "Optional" setting unchecked
Created a node and got an error about there being no end date.
Checked the "Optional" setting
Created a node without an end date and could save just fine.
Using a 2nd content type
Reused the field and set the setting to the opposite of the first content type
Settings were honored on both content types.
LGTM!
Comment #202
kunal.sachdev commentedComment #203
simeNice work on this issue and moving out of storage settings.
For the first issue, would this work better? Allow the end date to be optional, even if the date range is required.
For the second issue, that would be solved with #states api.
Comment #204
simeComment #205
lauriiiI haven't looked in the MR yet but the checkbox shouldn't have anything to do with the "Required" checkbox. The "Required" checkbox controls if the datetime range field must contain a value. The new checkbox added here, defines what is a valid value for the datetime range field; whether we expect to always have a pair of start and end, or can we accept just the start date. The new setting should impact the validation even when the field is not required. If the field is not marked as required, the end date should be still required when the user enters a start date.
Comment #206
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #209
simeUsability review
We discussed this issue at #3398823: Drupal Usability Meeting 2023-11-10. That issue will have a link to a recording of the meeting. For the record, the attendees at the usability meeting were @AaronMcHale, @Emma Horrell, @benjifisher, @rkoller, @sime, and @simohell. If you want more feedback from the usability team, a good way to reach out is in the #ux channel in Slack.
In the review we compared the setup of this option to the LinkItem options. The recommendation was that the checkbox "Optional end date" be converted to radios. This has two benefits
I have coded this change and created a MR against the existing MR, rather than just adding to the current MR. The functionality currently works as expected, so aside from changes to interface language, this is a positive review of the existing MR.
https://git.drupalcode.org/issue/drupal-2794481/-/merge_requests/2
I'm not confident that I have the language right, but I opted to be a little verbose. This isn't easy text due to the confusion that is caused in combination with the "required" option.
Comment #210
rkollerThanks for adding the meeting summary @sime! There are two additional details to note that were mentioned on Friday.
1. If you add a field to a content type you have the field type
Date and timeand the dedicated field typeDate range. Wouldn't it be more consistent to addDate rangeas an option to theDate and timefield type? (in the context of the changes #3356894: Make field selection less overwhelming by introducing groups introduced)2. Out of the scope for this issue but the error message for the case if you leave the start date empty (the required field checkbox unchecked) and have end date required or not required. in both cases the user gets the error message
This value should not be null. In particular for none technical users that message isn't helpful at all.In regards of the microcopy for the radio button group introduced in MR5356. I wonder if the labels could be simplified? How about the following. Provide the context for the radio button group by changing its title from
Optional valuesto simplyEnd date, that way end date hasn't to be used within the list of available options? For the two available options instead ofNot applicable, the end date is not optionalsimply useRequiredwhile changingOptional end dateto justOptional? And i wonder if the description could be simplified as well to something likeApplies to required and not required fields.?but in general after testing MR536 going with the radio button pattern is indeed way more clear compared to the single checkbox pattern from my perspective.
Comment #211
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #212
sime#210-1. I think i missed that part of the meeting. I think it's safe leaving this out of scope since date vs daterange have different storage needs, both occupy a lot of use-cases, and daterange is not visible if not installed.
#210-2. Looking more closely at this, maybe this is caused by changing the constraint validation upsets the default HTML5 validation. It's arguably in scope and I'm reading back and I don't see anywhere that we made it out of scope.
#210-3. I really like this wording @rkoller! I did add a variation of the description where I think we can be more verbose
Applies regardless of whether the whole field is required., but primarily the label and option labels are perfect. I have done a screenshot for those two options visual.Comment #213
simeI have pushed a fix for "This value should not be null" and updated the widget option labels on my MR https://git.drupalcode.org/issue/drupal-2794481/-/merge_requests/2
Just confirming that my MR is against @kunal.sachdev's latest branch/MR as at #200.
Comment #214
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #215
simeThe above CSpell error will be fixed if we merge my branch into the MR branch.
Comment #216
rkollerre #212
#210-1 yeah on second thought i completely agree, you are right. it is out of the scope for this issue and should go into a followup issue instead. the grouping has nothing to do what this issue is about.
but for the follow up issue from my perspective i strongly vote to sort the date range as an option under the
Date and timegroup so all field types about date and time are contained there. those groups are user facing and are from my understanding communicating a common thematic functional topic. and even if a date field and a date range field have a different storage need i am not sure if it is necessary and beneficial to have two separate groups for them. i would keep the number of groups concise imho.#210-3 one note regarding the optional-option. my suggestion was to use just
Optionalinstead ofOptional end datesince "end date" is already used in the title now - therefore i would strike the end date in the option label.About the description. I am torn, neither my own suggestion nor the variation you've proposed in #212 completely convinced me. The problem with my own is the "required and not required" is sort of hard to comprehend even though it is clear and is using the wording from the "required field" checkbox label. on the other hand "regardless of whether the whole" is sort of verbose and using the passive voice at the end (i am not sure how to express what it is but from a none native speakers perspective i am getting the core message the sentence communicates but it still makes me think each time i read it) . both variants are not perfect and make the reader think but i consider each variant still an improvement. i am fine with either of the two if no one else comes up with another variant.
#213 i've tried to apply https://git.drupalcode.org/issue/drupal-2794481/-/merge_requests/2.diff with composer patches instead of MR5356 but it failed to apply.
Comment #217
sime@rkoller looks like @kunal.sachdev has merged (thanks @kunal.sachdev!), so no need to mess with my extra MR now, just use the normal diff.
I've created #3401464: Date range should be in the date_time category for the grouping/sorting. It is easy to group it but it requires some UI text to be written.
I have changed
t('Optional end date')to$this->t('Optional'),and pushed. Good change. So that leaves us with this description text which I agree might be improved.Comment #218
kunal.sachdev commentedComment #219
rkollerat first thanks to @kunal.sachdev for the merge and the follow up work!
and thanks for opening up a follow-up issue for the grouping/sorting @sime as well as changing the label for the option! looks good! About the description. One detail i realized, why not simply strike the word "whole"? It isn't adding any mandatory information, and you aren't able to require a field in part anyway? I also searched if there is a way to express "regardless of whether" in a more plain way. The only variant i came up with was:
Applies no matter if the field is required.but it reads a bit rough due to the use of "if". so not sure if there is a more seamless and easy reading alternative for "regardless of whether". but by striking the word whole your variant also looks better?
Applies regardless of whether the field is required.I leave the final decision up to the english native speakers. ;)
Comment #220
sime> Applies regardless of whether the
wholefield is required.I've pushed this change, I think it's looking pretty good at this point.
Comment #221
rkollerThanks! I agree looks pretty good. One detail left to clarify in regards of the mentioned changes in #213. I've quickly retest with the current state of the MR ("required field" unchecked, end date option, and on the node only entered an end date and left the start date empty) and i still run into the
This value should not be null.error message.p.s. apologies just realized i've attached a screenshot about the ui components order to the comment. i initially thought it might be a potential minor issue that the required field checkbox and the radio buttons group should be next to each other. but on second thought it is also totally valid in the current order. but forgot to remove the image again. so please ignore the attached image.
Comment #222
solideogloria commentedI agree that "Applies regardless of whether the field is required." sounds good.
Comment #223
smustgrave commentedCan confirm I got the same error as @rkoller in #221
Comment #224
simeYeah same for me... not sure what changed there. I'm confident this needs (more) functional tests at least for optional fields. I plan to work on this.
Comment #225
narendrarWhile creating a date range field, one of the End date value (Required/Optional) should be selected by default.

Right now it is allowed to save without selecting any value.
Comment #227
sime#225 @narendraR - I looked at the LinkItem for comparison and note that it also sets initial defaults - so I think this is valid point and I've made this change. The initial default that I have chosen is to make the end date mandatory by default.
I've reverted my attempt to fix "This value should not be null" UX issue when the field is optional. It believe it would need to have the NotNull constraint (that is coming through via the TypedData I think, and not any parent classes) replaced completely. It's a bit beyond me to fix this. Since it has been considered out of scope previously (it is an existing problem) I'll mark this Ready for reivew again.
Comment #228
simeComment #229
smustgrave commentedIf we are going to leave the message as is is there a follow up for fixing it?
Comment #230
narendrarRe:
Agree
Code changes looks good to me. Tested manually and things are working as expected. Checked schema and config level changes also.
Comment #231
sime@smustgrave yes i have added a #4 TBA in the follow up issues, If no one objects i'll create that issue soon with my notes from investigating it. Follow up issues are currently
Comment #232
simeI've made an issue for the UX issue.
Comment #233
simeComment #234
smustgrave commentedThanks for opening that.
Since that was the last item believe this may be good to go.
Comment #235
alexpottThe current UI is confusing because we have the statement "Applies regardless of whether the field is required". This is not true. If the date range is not required and the end date is required then you are able to save a field without an end date. This is a good thing. But this text does not make it clear that this is the way this will be work. I think the ui needs refining to be something like this...
Under the hood this needs to be split out into the two settings but the UI should focus on user interactions not the underlying data model.
Comment #236
simeMost of the difficulty around wording is because of the wording of the separate Required checkbox that obviously comes from the base/parent class. Do we want to explore unifying the two form elements (while retaining the underlying config structure)?
Comment #237
berdirI also thought the current description adds more confusion than it helps. We have an existing pattern for this with the link field, that is just a separate element with hidden/optional/required.
I'm not sure about merging the two settings together and altering the form elements of the parent and if that's a good idea from a technical perspective.
The proposed solution IMHO is also not correct. Optional as a separate option isn't correct. Even if the field is not required, if a start date is given, you must provide an end date as well. So one more reason to not mix it. IMHO the description should be conditional, like "Whether an end date must be provided *if* a start date is given".
Comment #238
devad commentedRe: #237
This description is clear and easy to understand IMHO.
The only problem with this description is that it may not fit nicely the possible future additional settings: #3395096: Allow start date to be optional. Elaborated in my next post.
Comment #239
devad commentedFor full set of use case radio options I suppose we should have here:
Case a - when the "Required" field checkbox is not checked
1a. End date is required when the start date is provided (x)
2a. End date is optional when the start date is provided
(3a.) End date can be provided even if the start date is not provided
Case b - when the "Required" field checkbox is checked
1b. Both start and end dates are required (x)
2b. Start date is required only
(3b.) End date is required only
(4b.) Start date or end date is required
The current default behavior options (1a and 1b) are marked with the (x) sign. I suppose the best is to keep these two radio options selected by default for BC reasons.
The radio options 3a, 3b and 4b are postponed for later addition. The follow-up issue is here: #3395096: Allow start date to be optional
So, we have focus on 1a, 1b, 2a and 2b options here... but it would not be bad to make them easily compatible with the future additional options as well.
Note: English is not my native language, so better wordings are welcomed always.
Comment #240
lauriii+1 to #237. Let's move figuring out support for #3395096: Allow start date to be optional to the follow-up. We'll have to change the UI once we introduce the more complex set of settings, but we don't have to do that here.
Comment #241
tobas1996 commentedIm trying to attach that "diff": https://git.drupalcode.org/project/drupal/-/merge_requests/4619.diff on a Drupal 10.1.6 version, and It does not work. Could you review it please?
I've seen that the problem its on the DateTimeRangeTrait.php .
Grateful for your work. Thanks
Comment #242
simeSo revert it to a checkbox is my takeaway from this? I did restructure things to be able to handle optional start date without any impacts on the config schema. But also because it allowed us to break up the description from a long sentence.
Comment #243
kunal.sachdev commentedComment #244
smustgrave commentedBelieve additional feedback has been addressed.
BTW thank goodness for gitlab, if this ticket were still comments and patches the ticket may not load haha.
Comment #245
simelauriii/berdir/alexpott have outstanding concerns. Maybe it's pedantic but i want to address some concerns again.
"It should work like LinkItem" - structurally the setting is working like LinkItem, being a setting with enumerated options. But I think the comparison should stop there. IMO there is subtle difference between LinkItem "make the label optional" and DataRangeItem "make half of the data structure optional".
"We made it more complex by considering future optional start date" - agreed, but it helps to split the language up because you can describe each radio option separately, and the side effect is that it will save a future update hook in #3395096: Allow start date to be optional. If core devs want a boolean option, then I will re-roll the patch because I was the one who turned the checkbox into radios. (Note, this would make it less like LinkItem.)
"we shouldn't use OPTIONAL_ language in the code" - I don't think this should be a deal breaker. when i was looking at the code, i found that differentiating between "required" (field) and "required" (part of a field) is mental gymnastics. This is made worse when you start picking through HTML5 validation and the NotNull constraint. So using the language "part of this required field is optional in this situation" I think is a solid step, and also matches how we describe it in the issue title.
"The form labels are confusing" - totally valid. rkoller and I considered different options and think it's pretty close. If we can settle on the underlying data model/code then we can finalise the labels?
Comment #246
smustgrave commentedSounds like it should be back in review
Comment #247
alexpottI still think that having the required checkbox and separate radios for the end date is confusing. I think the concerns about unifying everything into a single set of radios expressed by @Berdir in #237 are incorrect. The UI does not have to match the underlying data structure.
This change gives us three states to deal with:
If we do the follow-up to make it possible to just require the end date and not the start date then that adds "end date required" to this list and the it'll be simple to add the list of radio options.
Comment #248
smustgrave commented. Should this go to the UX team?
Comment #249
devad commentedMaybe it's a bit too late to radically change the concept here but I'll ask nevertheless...
Is it possible to have here two different sets of radios which are shown/hidden by JavaScript?
One set available if the "Required" checkbox is unchecked and the other set of radios available when the "Required" checkbox is checked. As suggested in comment #239.
That would give us enough flexibility for all options we need both currently and in the future for #3395096: Allow start date to be optional.
Comment #250
smustgrave commentedLets get this one back on the radar.
MR currently is unmergable.
@alexpott #247 what additional task should be added to the issue summary?
Comment #251
kunal.sachdev commentedComment #252
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #253
webengr commentedwow, this has been an issue for 7+ years?
Any reason not to just use https://www.drupal.org/project/optional_end_date
?
Comment #254
solideogloria commented@webengr If you go to that module, it even says on the main page that it's just a workaround until this is properly implemented in Core. I think we all want to see it in Core.
Comment #255
kunal.sachdev commentedComment #256
smustgrave commented@alexpott in #247 believe the follow up is/should be covered in #3395096: Allow start date to be optional.
Re-tested the MR
When using the End-date as required there is no visual indicator that it is required. Hopefully an easy tweak.
Functionality wise it was working as expected.
Comment #257
lauriiiThe challenge with #247 is that there's no such state as nothing required. When nothing is required, if you enter end date, the start date would still be required. I think the current proposal is good enough, and that's why I think we should move forward with it. We can implement improvements on top of this in future.
Comment #258
smustgrave commentedSo fine with the accessibility issue of no required indicator?
Comment #259
alexpottYes there is - the field can be empty. If the required is unticked that you do not have to enter a start date or an end date.
Comment #260
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #261
douggreen commentedDoes this do anything that #2827055: Add option to show only start or end date in the DateTime Range custom formatter doesn't do? If it does, I think it needs to be re-worked now that the other issue has committed.
Comment #262
lisotton commentedMaking #153 compatible with Drupal 10.3.
Comment #263
dqd#261: This issue #2827055: Add option to show only start or end date in the DateTime Range custom formatter only changes the display options on date range fields. This issue here is about turning the required end date to an optional end date. From a glimpse I think "needs to be reworked" is a little bit over the top here, because as @laurii sad in #257:
That's why I will set it to NR for some thoughts on if we can move on or not with the latest test bot report and a re-roll.
Comment #264
smustgrave commentedLeft some comments on the MR.
Comment #265
smustgrave commentedTried to address some of the typehints and schema validation. Tests are green
Comment #267
smustgrave commentedAddressed the feedback
Comment #268
arejo commentedThe branch was tested as checked out in a gitpod and as applied to an existing site.
I have tested with and without end date, altered the required state of the end date of the date range field and tested the update scripts. It all seems to do the job as expected in the manual tests. This seems good to go for me.
Comment #269
steinmb commentedI read through the MR changes and unit including the kernel tests for the API change, looks OK. Also tested the
hook_update_N()on HEAD. The change recored looks OK. We prob. still need initiative maintainers to step in? But except that, I think we might be done.Comment #270
jonathanshawThe alexpott and laurii debate from 237/247/259 is unresolved.
Comment #271
quietone commentedI read this issue and tested the MR. Thank you to those you contributed to keeping the issue summary up to date. That is really helpful.
I see that all the followups have been made, so that is done. And this has had a UX review and the MR was changed accordingly. However, the description for the new end date option uses a suggestion made after the review, in #237. During my testing, I think that change is correct, that is, it made sense to me when seeing the form for the first time.
Of most concern is #270 saying that the conversation in #237/#247/#259 is unresolved. I am not sure about that. I think that alexpott answered that in #259. Did I miss something?
Next, I took a look at the MR and I see it is not meeting coding standards. I will review that after a break.
Comment #272
quietone commentedI made some comments and suggestions in the MR that need work.
I read the change record and that too needs to be updated. The change record implies the change is for D8, that can just be removed. Change records have an existing field to identify the first release where the change was made. The change record should also identify what the change in the UI is. It should have some text or a pointer to let the reader know how that UI changed.
Comment #273
quietone commentedAnd one more question, should the follow up issue that were made here be added either as a child or as related to #2543958: [meta] DateTime Module Improvements
Comment #274
jonathanshawIn #235 @alexpott makes a proposal to use a different approach. In #237 @berdir says it won't work, which @laurii agrees with in #240. But alexpott in #247 disagrees with #237. @laurii countergargues in #257, and @alexpott refutes in #259.
I don't think @alexpott's suggestion from #237 has been implemented, but he's not given up arguing for it either.
Comment #275
joelpittetUpdated CR as per #273 @quietone's suggestions to remove D8 and a bit more.