Problem/Motivation

The Date module for D7 had a “all day”-option. A field could be created with a checkbox labeled “all day” and when checked, the time field was removed, and only a date field remained.

Many calendaring systems, including Google and Apple's native calendar, support this. It's a very common UI pattern, and makes life a lot easier for content editors.

Currently, core supports either a "Datetime" field, or a "Date-only" field, but not a single field where the time part is optional. Being forced to use 2 totally separate fields for this is a huge problem, because then views of events get all complicated and weird. "We" just want a single field, but some of the events have a specific time, and others are "all-day".

Proposed resolution

https://www.drupal.org/project/date_all_day now exists to try to solve this problem.

Basically, we need a checkbox on all date widgets for "all day". The default value of this checkbox can/should be a widget setting. If checked, the time elements of the field input should disappear, not be required, validated, etc.

How this should be stored in the DB is TBD. The two most obvious choices are:

A) Add a separate column to the value table.

B) Overload the existing datetime with special values that indicate "all-day" (e.g. time as 00:00:00 or something).

Remaining tasks

  1. Decide if date_all_day is the right approach.
  2. If so, turn it into a patch against core.
  3. If not, figure out the right approach and implement it. This includes deciding on how the all-day bit should be stored with each field value.
  4. Write / update a lot of tests.
  5. Review/revise/repeat.
  6. Commit.

User interface changes

- New widget settings to control all-day behavior (should it be allowed as an option, and if so, what the default should be).
- If so configured, new checkbox on datetime* field widgets (e.g. on entity forms).
- Changes to field formatters that take all-day into account for how a given date value is displayed.

API changes

TBD.
Perhaps changes to the datetime form Element.

Data model changes

TBD.
Maybe none.
Maybe a new column in the schema to store datetime fields.

Original report by rolfmeijer

The Date module for D7 had a “all day”-option. A field could be created with a checkbox labeled “all day” en when checked the the time field was removed, and only a date field remained. In the db the time entry was written as 00:00:00.

I’m not sure this is still the best way to build a function like this (as you could not have a date with the time set to 00:00:00 because that would mean it is a “all day”-date), but it would be nice to be able to make the time field optional when a date-type of date-time is chosen.

Are there any plans to bring this functionality to D8 core, or should this be made available as a contrib module?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rolfmeijer created an issue. See original summary.

mpdonadio’s picture

I need to check a Drupal 7 site later, but I thought this was implemented as a date range in the backend where the date was the same, but the start time was 00:00:00 and the end time was 23:59:59. We may be able to do this once #2161337: Add a Date Range field type with support for end date lands, possibly as part of that if it isn't that hard.

rolfmeijer’s picture

@mpdonadio Thanks for your answer, that would be great.

jhedstrom’s picture

Similar to an all-day option, a default of 'same day' option, similar to how the https://www.drupal.org/project/date_single_day module worked in 7.x would be nice. I think both of these could be achieved in a purely front-end fashion (with backend configuration perhaps).

#2699895: Add settings to define #date_increment for datetime and datetime_range 'default' widgets could potentially resolve this too...

mpdonadio’s picture

Status: Active » Closed (duplicate)
AaronBauman’s picture

Version: 8.2.x-dev » 8.7.x-dev
Status: Closed (duplicate) » Active

Not sure if there was a misunderstanding of the request, but #2161337 does not address this issue.

The request, as i understand it, is for a feature similar to google calendar's "all day" option.

That is this:
Given a date + time field, for an individual field value, allow users to input only a date or somehow indicate that "time" is not relevant to the given value.

In other words, for the same field, sometimes i want a time and sometimes i don't.
In D7, date_all_day module was part of date module and worked like so:
* "all day" checkbox on the form widget, hides the time field
* submitting "all day" checkbox checked caused the date-time value to be saved with a time of 11:59:59 (or maybe 00:00:01, i don't quite remember)
* special handling in date module, e.g. views handlers, to make sure this works as expected

This is how e.g. google calendar works.
This feature is not in 8.7.x
A date-time field in 8.7.x requires a time to be entered.
Date-only and date-all-day fields do not allow a time to be entered, ever.

bkosborne’s picture

Well, in core right now, when adding a new Date Range field, you get three options in the field storage config:

  • Date and Time
  • Date only
  • All day

So what's the difference between "Date only" and "All day"? When you select "Date only", literally only a date is stored in the database (2018-12-12). If you select "All day", then a full date and time is stored in the database, but the start date is set to midnight (the 1st second of the day), and the end date is set to 1 second before midnight on the end date.

Given that, I don't see the benefit of having this "All day" option in core, at least as it stands now, because why wouldn't you just use the "Date only" option?

What's needed is the flexibility to choose if an individual date you're adding is an all day date or not, which is not currently supported.

While I think core should support this, I think that this is also something that contrib can solve. In fact someone has already tried: https://www.drupal.org/project/date_all_day

bkosborne’s picture

AaronBauman’s picture

We're talking about 2 different things, so let me try to clarify.

You're talking about a field setting which allows creation of fields to collect either a date, or a date time.
In that scenario, a user would require 2 different fields per content type if they wanted the content type to collect both dates and date-times.

I'm talking about a UX option for a date-time field, so that a content manager can enter either a date or a date-time into a single field.

For example, as a content manager (or site builder), I'm creating an Event.
I don't want two separate fields to represent the event date - this will create headaches down the line with views, with property queries, etc.
I want one single field "event date" which collects the date of the event, and optionally the time.
If the event has a specific time, i want the time to be included in the "event date" field.
If the event does not have a specific time, i want to either leave the time blank or select an "all day" checkbox to indicate the equivalent.

This is how it worked in D7.
This is how google calendar works.
This is a pretty standard calendar / event feature.

AaronBauman’s picture

Thanks for the link - I see this line of conversation is in progress on the older issue #2699895
Closing as duplicate

bkosborne’s picture

Hi Aaron - we're definitely on the same page. The UX option you're talking about I mentioned:

I'm talking about a UX option for a date-time field, so that a content manager can enter either a date or a date-time into a single field.

The contrib module "date all day" does this (though I think it should also be in core).

dww’s picture

Title: Support for "all day"-option » Support for "all day" option for each value of a datetime field
Issue summary: View changes
Status: Closed (duplicate) » Active

Let's keep this a separate feature request from #2699895: Add settings to define #date_increment for datetime and datetime_range 'default' widgets.

#2699895 is about a field-level setting that controls what granularity that field will support across all entities using that field instance.

This issue is about a checkbox on every entity that has a datetime field to let content editors opt-out of specifying a time for that particular entity.

Ideally, this is not *yet another* field type and widget/formatter ecosystem. This should just be part of the core datetime and datetime_range field types. Then, widgets and formatters can provide and interpret the value of the checkbox as appropriate.

This support could/should perhaps reach all the way down into the datetime form Element itself. TBD.

If we try to accomplish both features as part of #2699895, we're going to fail.

Just gave this issue a proper summary.

Trying to set a more specific title to aid in untangling the confusion. We already use "field instance" to mean a specific field on a specific entity type and bundle. What's the right terminology for an instance of a field on each entity using the field? ;) Those are "field values", no? Help me out here if there's better language to be using. But I think the root of the matter for this issue is that we want every datetime *value* to know if it's all-day or not.

Thanks!
-Derek

bkosborne’s picture

For date range fields, I don't think there should be a separate "all day" option for the start AND end date. It should be one checkbox that affects both. This is how all calendaring systems that I've tested work (Google Calendar, Apple Calendar, Outlook) and IMO reduces complexity. It's also how it worked in D7.

How I think this should be implemented is very close to how the "Date All Day" contrib module is doing it. One key difference is what I discussed above (don't add an "all day" checkbox for both parts of a range).

  • Additional boolean field property that tracks of the datetime/range is "all day" or not. This is controlled on the field widget with a simple "all day" checkbox.
  • Dates are still always stored with a full day and time in the database, even if "all day" is checked. For a single datetime field, the time is set to midnight (first second of the day). For a datetime range, the start is set to midnight (first second of the day) and the end is set to the last second of the same day. This allows queries that use hour/minute/second granularity to work properly.
  • Widget formatter would need some javascript. When the "all day" checkbox is checked, then the time field needs to be hidden. It also needs to be set to the appropriate time as described above.
  • Field formatters would use the "all day" boolean value on the field to determine if the date should be output with a hour/minute/second or not. For this to really work properly, the formatters would probably need to accept TWO date format options. One date format is used if the date is a day + time, and the other is used just for day only (all day).
AaronBauman’s picture

Agreed generally with #12 and #13 - thank you for re-opening.

My quick feedback:

The two most obvious choices are:
A) Add a separate column to the value table.
B) Overload the existing datetime with special values that indicate "all-day" (e.g. time as 00:00:00 or something).

Probably we'll want to use both of these.
While a time of 00:00:01 or 23:59:59 might be an edge case, we may as well eliminate any potential confusion by including a new column to identify those dates specifically.

For date range fields, I don't think there should be a separate "all day" option for the start AND end date. It should be one checkbox that affects both.

I agree with this.
Either the dates have times on them, or they don't.
Mixing and matching just doesn't seem like a legit use case.

For a datetime range, the start is set to midnight (first second of the day) and the end is set to the last second of the same day

"the end is set to the last second of the end date" because they might start and end on different dates.

Widget formatter would need some javascript. When the "all day" checkbox is checked, then the time field needs to be hidden. It also needs to be set to the appropriate time as described above.

Agreed, javascript will be necessary to polish the UX.
The time value should be set on during validate/submit.

We're in agreement this is only for datetime field right?
We don't need this option for timestamp fields, because that would just be silly, right?
Just brainstorming: datetime stores data as varchar in DATE_ATOM format (at least in MySQL).
Strictly speaking, there's no reason we need to write the time, so long as we don't mind using different formats based on the all-day option.

bkosborne’s picture

Title: Support for "all day" option for each value of a datetime field » Support a per-instance "all-day" option for datetime and datetime range fields

We don't need this option for timestamp fields, because that would just be silly, right?

Aside from the entity created/changed base field definitions, is it even possible to store a date in D8 as a timestamp?

Just brainstorming: datetime stores data as varchar in DATE_ATOM format (at least in MySQL).
Strictly speaking, there's no reason we need to write the time, so long as we don't mind using different formats based on the all-day option.

It's not quite DATE_ATOM, because Drupal doesn't store the timezone info at the end (since everything is UTC). In fact it doesn't even use a MySQL datetime storage type, just a VARCHAR. So, yes, I think technically we could store just the date, but I'm not sure that's a good approach here. I think storing the complete date and time will break the fewest things that rely on there being a time value there.

Also, I know you agreed already, but to further enforce that we should not have separate "all day" checkboxes for both the start AND end of a range, refer to RFC 5545 (iCalendar spec) which talks about representing the "end date" of a range:

this property
defines the date and time by which the event ends. The value type
of this property MUST be the same as the "DTSTART" property
, and
its value MUST be later in time than the value of the "DTSTART"
property.

(emphasis mine). What it means by "value type" is either date + time or just a date without time. So iCal spec doesn't even allow you to mix and match them.

I've updated the title to reflect that.

AaronBauman’s picture

Aside from the entity created/changed base field definitions, is it even possible to store a date in D8 as a timestamp?

I was referring to the Timestamp field type.
I don't know if there's overlap between widgets or formatters, but either way I think we can rule out support for timestamp, because a timestamp without a time just doesn't make sense.

So, yes, I think technically we could store just the date, but I'm not sure that's a good approach here. I think storing the complete date and time will break the fewest things that rely on there being a time value there.

Makes sense. With an eye towards not breaking D8, I guess let's keep this possibility open for D9 if it simplifies implementation.

bkosborne’s picture

But I'd love to be more explicit with an actual bit we can check for this. That said, an upgrade path for such an approach will surely turn this into a 300 comment issue that'll never land in core. :/ Thanks core development process. ;) So yeah, we might have to live with it.

I agree 100% that we need a separate bit on the field that tracks if it's all day or not. It would be a tinyint field that stores a 0 or 1. We should not overload the meaning of the time values to infer an all day. That is how the Drupal 7 date module works and I believe there's a few issues in queue about problems this causes.

But yes, this causes a problem for migrations for sure and makes the feature more complicated. I think we all want to avoid having a separate date field type. But... I don't know how else to handle this. Core has already gone down the path of multiple date field types for various options, and the time to change that has probably passed. I would say we could aim for Drupal 9, but that's not really how Drupal development works anymore. Drupal 9 is not necessarily an opportunity to introduce breaking changes. It's supposed to just be like another Drupal 8 feature release.

As for focusing work on the Date all Day contrib module, I think that's a good idea. I think we ultimately need to create a 2.x branch of that module though, because that module is doing more than we need and already has a beta release...

dww’s picture

Core has already gone down the path of multiple date field types for various options, and the time to change that has probably passed.

I sure hope not. That decision is creating a *ton* of problems in the date ecosystem. We can't just compound the problem by forking field types for every new use case. It'll probably be hard, but I'm much more in favor of pushing back against this trend than continuing down that (IMHO, disastrous) path.

Maybe we need some kind of D8 date* summit to get interested parties and stakeholders in a direct discussion on the way forward, how to best coordinate and focus efforts, etc.

For now, yes, let's gang up on date_all_day, perhaps an 8.x-2.x branch. See you over there. ;)

Cheers,
-Derek

bwoods’s picture

I recently checked out the date_all_day module but noticed a few things that didn't seem to work as expected. Probably the main one was the fact that there are two "all day" checkboxes, which is unnecessary.

I've been working on an update to datetime_range that includes just one checkbox and an additional column for any field using datetime_range. I'm close to finishing the first round of the edits and will post a patch here hopefully by the end of the week.

bwoods’s picture

I'm adding the patch I created, although I'm sure it could use a little help.

Applying this patch should give an admin the ability to allow for all-day events via the datetime_range module. While it could also be useful for datetime, I thought applying to datetime_range would be more useful since, to me, "all day" indicates a range of time.

On install, a new column is created in the database for fields using the datetime_range type. This field probably should be tinyint, but I used int because I ran into an issue when running DB updates. Any advice on why that didn't work would be greatly appreciated!

Upon creating the field, there is a checkbox that asks the admin if an all-day option should be available per field.

Assuming that this is checked, when an admin creates a new code that includes a datetime_range field, there will be a checkbox available to indicate if the event is all day. Clicking the checkbox will hide the time elements and automatically input 00:00:00 for the start time and 11:59:59 for end time. A caveat here - I prefer using 00:00:00 for end time here so that I don't have to worry about additional timezone handling. But logically, an all-day event would go all day, so I left it that way in the patch. This can be easily changed in the JS.

Another caveat - I'm not using the constant DATETIME_TYPE_ALLDAY for anything, so I have not updated the function massageFormValues in any way. It seems weird to me that this was unnecessary, but since I'm using the Calendar module and the all-day functions available there, I didn't need to modify. Perhaps some code in Calendar needs to be adjusted to use this variable. Additionally, I can pass along modifications I made in the Calendar module to tie in with this, although it seems that some changes have been made to that module now, so I will need to update.

EDIT: Modified start time to 00:00:00 - thanks to dww for pointing out the error.

dww’s picture

Status: Active » Needs work
Issue tags: +Needs tests

Great, thanks! I haven't tried testing at all, and I don't have a quick answer to your problem with tinyint vs. int.

A few obvious problems on an initial skim of the patch:

1.

+++ b/core/modules/datetime_range/datetime_range.info.yml

These changes are bogus for this patch.

2.

+ * Post-update functions for Datetime Range module.
...
+function datetime_range_update_8001() {

So far, the only thing in that file is a regular update hook, not a "post-update function".

3.

+  // find fields that use datetime_range
+  $connection = \Drupal::database();
+  $query = $connection->query("SELECT name FROM {config} WHERE data LIKE '%datetime_range%' AND name LIKE 'field.field.node.%'");
+  $result = $query->fetchAll();

You don't want to directly query the DB like this, you need to use the standard config and/or entity manager APIs for this.

4. I know #2419131: [PP-1] #states attribute does not work on #type datetime is still not fixed in core, but I wonder if you can use #states directly on the time elements within each 'datetime', instead of having to do this manually via core/modules/datetime_range/js/datetime_range.js. If you do need to do it manually, this should be a datetime_range.es6.js and a compiled version of datetime_range.js.

5.

+        /** @var \Drupal\Core\Datetime\DrupalDateTime $all_day */
+        $all_day = $item->all_day;
 

I thought $all_day is a bool, not a DrupalDateTime. Happens in 3 places in the patch.

6. The user-facing help text (labels, descriptions, etc) needs some help. ;)

7.

+        '#attributes' => ['class'=>['check_group']],

Code style: should be '#attributes' => ['class' => ['check_group']],.

8. Same bogus changes to datetime_range_test.info.yml as mentioned in #1 above.

9.

+    default_all_day:
+      type: string
+      label: 'Default all-day value'
 

Again, I thought this was a bool. Why does the config schema claim it's a "string"?

10. I might be missing it, but I don't see where we actually notice the all_day checkbox is set and do anything fancy with the submitted time values. Is that not included in your patch for some reason? OH, sorry, I see now. It only happens in the JS. That's not good. We want that remapping to happen w/o JS, both for folks using browsers with JS disabled, and for API-first-happiness.

Also note, your comment says: "Clicking the checkbox will hide the time elements and automatically input 12:00:00 for the start time and 11:59:59 for end time." but the patch uses 00:00:00 for start and 23:59:59 for end (which makes more sense).

11. We definitely want to add tests for this. Tagging accordingly. Feel free to set to "needs review" if you upload a new patch to address the rest of this (so the test bot will run), but we can't call this "RTBC" until there's good, verified test coverage.

Thanks again!
-Derek

bwoods’s picture

Thanks for reviewing the first pass. After testing a bit more, I noticed a couple of additional issues, so I've created another patch. It doesn't address the items you mentioned, so I'll go back and look into those as well. It's sort of a kludge of small pieces from other modules, so I'll work on cleaning up. I just wanted to be sure I put up something before I ultimately end up getting busy with something else :)

To your point 10, I agree that this should set the all-day constant that exists in the module already. The weird thing I noticed is that it doesn't seem particularly valuable for anything directly within datetime_range. Maybe that's why it was never hooked back up because it seems to really matter only for display purposes (or at least for functionality outside of this module).

Anyway, I'll try to work through the other items you mention and post another patch in the next few days. Thanks again!

Pancho’s picture

Priority: Normal » Major

While it could also be useful for datetime, I thought applying to datetime_range would be more useful since, to me, "all day" indicates a range of time.

Full ACK. 'All day' is a range rather than a point in time with just some UI magic. Finally one (or contrib) might be interested in all events happening this evening or might sort by end date. So a correct 'All day' feature may only be based on the datetime_range field type. Widget and formatter are a different thing. I'd even consider deprecating plain datetime as a field type and make it all be just different widgets and formatters of datetime_range.

Thanks, @bwoods for giving the stalling date feature issue #2699895: Add settings to define #date_increment for datetime and datetime_range 'default' widgets a new and productive direction! Unless you're just preparing another version of the patch, I might invest some time into it as I need 'all day' for a project and am personally abhorred from incompatible core module forks like "Date all day" (not blaming the creators/maintainers, neither sitebuilders using these - we need to have a better solution in order to be...

pushing back against this trend than continuing down that (IMHO, disastrous) path.

... as @dww correctly said.

Feel free to disagree, but for exactly this reason (avoid fragmentation or actually reconcile an already fragmented contrib ecosphere), I consider this a major feature.

AaronBauman’s picture

'All day' is a range rather than a point in time with just some UI
magic. Finally one (or contrib) might be interested in all events happening
this evening or might sort by end date. So a correct 'All day' feature may
only be based on the datetime_range field type.

I think I disagree with this.

"All Day" may have different semantic meaning than 00:00 to 23:59:
It may mean an event for which there is no designated time.
It may mean an entire working day, not necessarily 24 hours.
It may need to be treated differently from an event with a 24-hour timespan.

For these reasons, I think it probably needs to be collected as a separate data point, rather than relying on a time range hack.
At the least, an "all day" API needs to support these concerns.

Pancho’s picture

"All Day" may have different semantic meaning than 00:00 to 23:59:
It may mean an event for which there is no designated time.

In a way, yes. But semantically, I can't figure out what a calendar/working/whatever day may mean besides "from x to y" or "at some point between x and y" resp. "in a sub-range of x to y."

I agree this means we need a more fuzzy logic or at least lower granularity at presentation level (never ever display 00:00:00 to 23:59:59), but FWIW setting a reasonable start and end is semantically correct rather than a hack.

It may mean an entire working day, not necessarily 24 hours.

We (or contrib) may allow settings for what "all day" may actually represent rather than 00:00:00 to 23:59:59 in a particular TZ. This may be stored at field level or in the table together with the date range.

It may need to be treated differently from an event with a 24-hour timespan.

Sure, it may so. But there are so many more things that might need different treatment.

I'm not saying something like a point in time that's not a range wouldn't exist, but it's more often a simplified (or even mis-)representation. Surprisingly often, and I'd say more often than not dates are a range, and this is not limited to 'all day'. A second may be 18:35:00.0 through 18:35:00.999 with a granularity of 1 sec. A minute may be 18:35:21 through 18:36:20.999 with a granularity of 1 min. An hour may be Thu, 23:48:52 through Fri, 00:48:51.999 (all UTC or default site TZ or user/event TZ).

So, besides perusing start and end date, for all date ranges we need to add a semantically correct, meaningful maximum granularity that is either stored at field level or at input time. Otherwise the formatter will never know whether a range was meant to represent 1 day or 24 hours or exactly 1.440 minutes. In general, the formatter however has to respect this metadata, which may not always be easy, particularly if collected at input time. In contrast, single points in time (semantically these usually represent either the start or the end of a larger or smaller range) don't necessarily need granularity at input time and may be arbitrarily formatted at presentation time.

What else do we need at field level resp. in the table is a timezone attached to the date range, so the formatter may decide to render it as as "December 25, 2018" (user/event local time). Or - depending on the maximum granularity allowed - it may render it as "December 24, 2018 12:00 - December 25, 2018 11:59" or "December 24-25, 2018" (UTC or site default TZ).

For these reasons, I think it probably needs to be collected as a separate data point, rather than relying on a time range hack.

It's a range rather than a data point, so it's the other way around: we can't rely on a time point hack plus some flag and need to represent it correctly as a range. ;)

At the least, an "all day" API needs to support these concerns.

This one I fully agree with.

mpdonadio’s picture

Tagging this with Needs issue summary update, since I think we need to reframe the Problem/Motivation to help what the problem is so we need to know what we want to implement. Right now we have

datetime - date+time
datetime - date-only (no time is stored, and the presentation is time zone agnostic enforced by the field, eg Dec 25 is a holiday wherever it is observed)
daterange - date+time
daterange - date-only (no time is stored, and the presentation is time zone agnostic enforced by the field, eg I can block out the week I am on summer vacation on my calendar)
daterange- all-day (time is not collected, but is stored midnight to midnight from the author's time zone in the widget and presented in the viewer's time zone, I forget the concrete example I had for this)

And we have the related configurable parts and optional end date issues, features of which have all been alluded to recently in comments.

bwoods’s picture

@Pancho, unfortunately I haven't had time to devote to this, so feel free to chop to bits.

I think I'm in more agreement with @aaronbauman in that "all day" could have multiple meetings. Semantically it should mean something closer to a range, but many times I've seen it used as "some time during a particular day." I'm using this for a school website, so a regular holiday theoretically means from beginning to end, but if the school is closed, it's technically just the regular school hours. I think the only way you can group those types of "all-day" events together is with some other flag, which it seems that we are all in agreement on that.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

timwood’s picture

Hi. Was trying out the most recent patch from #23. The patch applies (to an 8.6.16 codebase), but no update is run when I run drush updb. Should the update hook schema number be 8601 (or even 8801? since this issue is slated to be for 8.8.x). Even if I change the update hook schema number to 8601, rebuild caches and try to run drush updb again, it still says there are no updates. Nevermind about this last point, I had an issue with my filesystem syncing into my docker container. I believe the update hook schema number still needs fixing.

/**
 * Add column for all-day toggle.
 * This is shown to users on the update.php page.
 */
function datetime_range_update_8001() {

  // define schema for new field

Without this update running, I'm getting the following error on config import.

Unexpected error during import with operation update for field.storage.node.field_event_date: Exception thrown while performing a schema update. SQLSTATE[42S22]: Column not found: 1054 Unknown column 'field_event_date_all_day' in 'where
clause': SELECT 1 AS expression
FROM
{node_revision__field_event_date} t
WHERE (field_event_date_value IS NOT NULL) OR (field_event_date_end_value IS NOT NULL) OR (field_event_date_all_day IS NOT NULL)
LIMIT 1 OFFSET 0; Array
(
)

Thanks in advance for any help or suggestions.

I noticed some inconsistencies with the 'All-day' option appearing on the node edit/add screen. On /node/add/event it doesn't display at all. On /node/NID/edit it displays for some nodes. Not sure why.

Finally, shouldn't the config for the date field instance be updated with the 'All-day option' choice? drush cex didn't indicate any change after successfully applying the patch, running drush updb and re-submitting the field instance config screen.

akalam’s picture

I'm working on having an stable solution on date_all_day module before proposing to the core. I will back here informing of the status once the following issue gets solved:
Make date_all_day a set of widgets and formatters for core's datetime_range field type

akalam’s picture

The last 8.x-1.0-beta3 of date_all_day release uses core's daterange field type and provides a widget and a set of formatters to display date ranges placing all day.
I think the module is stable enough so I would propose a patch based on the module (probably next week). There is is still work to do, like provide test coverage but I think we have a good starting point to work.

bburg’s picture

Hi all,

There still seems to be some questions regarding how an all-day date is represented. I know we aren't explicitly trying to support it, I'm just going to point out that the iCalendar spec simply drops the time component from the date string altogether, also where the end time is exclusive of the range. So a date range for an all day event would be:

Start: 20190926
End: 20190927

And the 27th would not be a part of the date range. No "00:00:00". This is important, because all-day and partial day events are displayed differently in most calendar applications. i.e. appears as a bar across the top of days in google calendar. See https://tools.ietf.org/html/rfc5545#section-3.6.1, here they call it "multi-day." I know this is tricky, because the PHP DateTime class appears to automatically add the time when you exclude it in the constructor.

I am chiming in here because I am the current maintainer of the Views iCal module (https://www.drupal.org/project/views_ical), and I am currently grappling with how to manage all-day events. Without an explicit method of incorporating that as a part of an existing date range field, I'm left to implicitly determine that a date is multi/

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

jedihe’s picture

Assigned: Unassigned » jedihe
jedihe’s picture

Issue tags: +Global2020
erik.erskine’s picture

We* had a very in-depth discussion about this during the DrupalCon global contribution day on Friday.

It's clear from some of the earlier comments on this issue that "all day" can mean different things, and these things aren't necessarily interchangable. We looked in detail at two approaches:

  • midnight to midnight
  • date with an optional time

Neither of these is right or wrong, but they are fundamentally different, and there isn't a middle ground as far as we can tell.

Hopefully by understanding the constraints of each, we can get a clearer picture of how to make this work for particular use cases.

Midnight to midnight

This is the "all day" concept as provided by date_all_day and smart_date modules.

  1. We can think of this as a couple of UI shortcuts:
    When editing: a checkbox that, when ticked, hides the start/end time elements and populates them for you with 00:00 and 23:59 respectively.
    When displaying: replacing "00:00-23:59" with the words "all day".

  2. This is a very simple concept to implement and it fits well with core's existing fields: we are still dealing with a range between two datetimes.

  3. We don't have the concept of a local date/time in Drupal: everything is stored in UTC and converted to/from a user's timezone upon reading /writing the database. People see datetime (and datetime range) values differently depending on their location. That's correct behaviour, but it does have implications for all day when using multiple timezones.

  4. Therefore: "All day" means "a 24 hour** (or multiple) period in a particular timezone". What's "all day" for you might be "6am-6am the next day" for me.

  5. Consequently, all input and output can vary according to a user's timezone.
    That's far reaching, all of these become "personalised":
    • widgets
    • formatters
    • views output
    • a views "is all day" filter (it will return different results)
    • any kind of calendar output

For many use cases this constraint will be perfectly acceptable. Given it's simple, and also almost complete, there's a motivation to get this working regardless of whether or not we go down another route.

Date with optional time

This facilitates mixing values that are date-only and date-with-time.

  1. First we need to recognise that the concept of a date is fundamentally different to a datetime. Dates with times vary according to your timezone, but dates without times do not. So any kind of magic number, like setting the time part to 00:00 isn't enough.
  2. We need some way to differentiate between the two kinds of value. The simplest is to examining the ISO-8601 strings (eg 2020-07-17 vs 2020-07-17T23:00:00. But it's probably going to be easier to have another column to denote this. It's redundant, but will make SQL easier. A boolean flag has been suggested.
  3. Views filtering suddenly gets more complicated. Consider two events: "My Birthday" (date-only) and "My Birthday party" (date & time).
    • The answer to "is it my birthday?" depends on my timezone
    • The answer to "is my birthday party happening now?" is the same regardless of my timezone
  4. Sorting is equally complicated. Consider the follwing events. The order varies according to your timezone:
    • New Year's Day
    • New Year celebrations in Australia
    • New Year celebrations in London
    • New Year celebrations in New York
  5. We're going to need new views plugins for the above. The queries they generate need to examine the "flag" column in point 2 (however that's implemented). Depending on the value, the plugin queries then either a) converting the values from UTC to local time, or b) treating it as local time directly. The conversion happens for datetimes, not for dates.

--

* credit due to @jedihe, @owenbush & @mandclu
** strictly speaking not exactly 24h because of DST changes, but the principle is the same

erik.erskine’s picture

#2632040: [PP-1] Add ability to select a timezone for datetime field might facilitate better presentation of all day whilst still using the midnight-to-midnight approach in #38.

That issue proposes storing the timezone name alongside the UTC value. That timezone name doesn't affect the value, it's just used as a formatting hint. The datetime formatters now have an option like this:

      Show the value in:
        [ x ]  the timezone of the user viewing it     <-- this is what we do now
        [   ]  the timezone it was created in

A custom formatter in contrib would then be able to produce something like this:

19 July 2020, all day (CEST)

but if you don't use that formatter, the fallback isn't wrong:

19 July 2020 23:00 to 20 July 2020 22:59

jedihe’s picture

Assigned: jedihe » Unassigned

Thanks for a great summary, @erik.erskine!

I'll just add a quick "inventory" of sub-tasks to be performed in order to port date_all_day into core.

date_all_day review

Functionality to port:

  • Schema updates (only if adding new properties to field storage, e.g. 'all_day' bool)
  • js library: handles "All day" checkbox in forms.
  • Widget
  • Formatters:
    • Plain
    • Default
    • Custom
  • Config:
    • core.date_format.date_all_day.yml (required or nice to have?)
  • Utility:
    • DateRangeAllDayHelper::isAllDay(): just checks if values stored match the special values for 'all-day' (00:00:00 and 23:59:59).

Functionality to not be ported:

  • hook_field_views_data(): looks like it's still there just to support the deprecated field type (daterange_all_day).
  • Widget handling of 'optional_end_date', as it it is backwards compatibility for date_all_day itself.

Improvements:

  • All day checkbox changes time values right in the browser. Bad UX that punishes curiosity.
  • Enabling all day + incomplete time makes the form fail "silently" (no visible error for the user).

Other questions:

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

DamienMcKenna’s picture

Having worked through this problem in the Date module for D7, I would urge using a separate db field to indicate a specific value is "all day", otherwise you're getting into the realm of "magic logic" that will only lead to problems.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

jaime@gingerrobot.com’s picture

Issue tags: +behaviors, +widget, +Usability

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.