Support a per-instance "all-day" option for datetime and datetime range fields

Created on 26 May 2016, about 9 years ago
Updated 13 May 2024, about 1 year ago

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?

Feature request
Status

Needs work

Version

11.0 🔥

Component
Datetime 

Last updated 3 days ago

Created by

🇳🇱Netherlands rolfmeijer

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

  • Usability

    Makes Drupal easier to use. Preferred over UX, D7UX, etc.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇵🇱Poland gugalamaciek

    Improved patch which covers:
    - adds all_day column in DB for datetime range fields. Set it as disabled for all existing data with datetime type
    - allow to enable all day dates for datetime type & set default value for it in field settings
    - widget to set all day, making sure that date is stored in UTC when all day is selected (in general timezone is ignored when all day event is set)
    - GraphQL - share allDay property for datetime range fields
    - formatter - for now only supported inn default formatter. You can specify date format for all day and non all day dates
    - js - when you'll select all day, time is set to 00:00:00 for start & end dates

  • First commit to issue fork.
  • 🇵🇱Poland gugalamaciek

    #50 is #49 extended with End date optional #153 ( https://www.drupal.org/project/drupal/issues/2794481#comment-14839868 Allow end date to be optional Needs review )

  • 🇮🇳India sakthi_dev

    @gugalamaciek, could you please share the diff. I have created an MR for 11.x 2ith #49.

  • Pipeline finished with Failed
    about 1 year ago
    Total: 195s
    #171445
  • 🇵🇱Poland gugalamaciek

    Ups... I forgot about schema updates. So this is #49 + schema fixes.

  • 🇵🇱Poland gugalamaciek

    @sakthi_dev I'll try to produce 11.x version in free minute... but can't promise when exactly.

  • 🇧🇪Belgium rp7

    Updated patch in #54 to be compatible with Drupal 10.4.6.
    I might take a stab at D11 soon.

  • 🇦🇹Austria mvonfrie

    I came across this issue when analyzing a problem with a site heavily using date range fields and showing different kind of problems with views showing wrong results. By reading through the comments here I finally figured out what causes those problems.

    in #2734255-7: Support a per-instance "all-day" option for datetime and datetime range fields ::

    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.

    #2734255-27: Support a per-instance "all-day" option for datetime and datetime range fields :

    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)

    The problem

    As Drupal datetime works with local time but stores them in the database as UTC, in my case for Central European Time (CET) this can lead to a date range July 14 - July 20 2025 being stored as 2025-07-13T22:00:00 - 2023-05-20T21:59:59. When you want to create a view filtering for start_date <= today <= end_date this can lead to queries like

    WHERE
    DATE_FORMAT(node__field_promotion_time.field_date_range_value, '%Y-%m-%d') <= DATE_FORMAT('2025-07-15', '%Y-%m-%d')
    AND
    DATE_FORMAT(node__field_promotion_time.field_date_range_end_value, '%Y-%m-%d') >= DATE_FORMAT('2025-07-15', '%Y-%m-%d')
    

    with actual values from database

    WHERE
    DATE_FORMAT('2025-07-13T22:00:00', '%Y-%m-%d') <= DATE_FORMAT('2025-07-15', '%Y-%m-%d')
    AND
    DATE_FORMAT('2023-05-20T21:59:59', '%Y-%m-%d') >= DATE_FORMAT('2025-07-15', '%Y-%m-%d')
    

    actually being

    WHERE
    '2025-07-13' <= '2025-07-15'
    AND
    '2023-05-20' >= '2025-07-15'
    

    starts showing the promotion already on July 13 instead of July 14.

    As MySQL only knows the date value and not the timezone to interpret it for and Views queries work on SQL level those kind of views will not work.

    My solution probably will be to change the field configuration from datetime_type = 'allday' to datetime_type = 'date' and write some heavy update logic to change all existing data accordingly.

    But I see at least two issues I have to create:

    1. Update documentation about the different datetime_type options on drupal.org as well as in the module's field storage UI to inform site builders and administrators what the different options mean. Because as my colleague who implemented those content types had wrong assumptions what allday for Drupal's fields means, others may have the same wrong assumptions as well (including myself until reading through this issue).
    2. Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem uses Drupal\datetime\DateTimeComputed which doesn't know about datetime_type = 'allday' and therefore treats it as datetime_type = 'datetime' which can lead to unexpected results.

    BTW, Drupal\datetime\DateTimeComputed states in it's parsing logic:

    // If the format did not include an explicit time portion, then the
    // time will be set from the current time instead. For consistency, we
    // set the time to 12:00:00 UTC for date-only fields. This is used so
    // that the local date portion is the same, across nearly all time
    // zones.
    // @see \Drupal\Component\Datetime\DateTimePlus::setDefaultDateTime()
    // @see http://php.net/manual/datetime.createfromformat.php

    which points out that T00:00:00 and T23:59:59 might not be the best options for allday values in respect to local timezone vs. UTC handling.

Production build 0.71.5 2024