Page MenuHomePhabricator

Implement "All Day" events
Closed, ResolvedPublic

Description

Calendar should support "All Day" events.

Related Objects

StatusAssignedTask
Resolvedepriestley
Resolvedepriestley
Resolvedepriestley
Resolvedlpriestley
Resolvedlpriestley
Wontfixlpriestley
Resolvedlpriestley
Resolvedepriestley
Openepriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedepriestley
Resolvedepriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Duplicatelpriestley
Resolvedlpriestley
ResolvedNone
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Duplicatelpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley
Resolvedlpriestley

Event Timeline

epriestley assigned this task to lpriestley.
epriestley raised the priority of this task from to Normal.
epriestley updated the task description. (Show Details)
epriestley added a project: Calendar.
epriestley added a subscriber: epriestley.

I think this is:

  • A flag on the event like isAllDay.
  • And a checkbox for it.
  • I guess that javascripts some magic to disable the time options?
  • Special treatment on new views.

For now, we can just:

  • Set the start time to 12:00 AM on the first day in the creator's timezone.
  • Set the end time to 11:59:59 PM on the last day in the creator's timezone.

For users in an earlier timezone, these events will show up on the wrong day. This is complicated to fix. We can ignore that for the first version.

I think the fix is:

  • Set the start time to 12:00 AM in the westernmost timezone (UTC - 12). For example, if the event is on "April 25", this is the first second that is "April 25" anywhere in the world.
  • Set the end time to 11:59:59 PM on the last day in the easternmost timezone (UTC + 14). This is the last second that is "April 25" anywhere in the world.

This means that a date range query for this event which includes a date the event occurs on will always find it, no matter which timezone the viewer is in (if any of the seconds in their local "April 25" are part of the range, the range will overlap with the event's range). Then:

  • After querying, adjust these events into the viewer's timezone before returning them from the Query class.
  • This involves adding new getEffectiveStartDate()-type methods and changing everything to use them.

This will create a few weird artifacts at page boundaries, but will otherwise be correct and cheap to query.

An alternative is to only store date information for these events, then do two separate queries for time ranges:

  • Find all events which are not "all day", and have times in the range.
  • Find all events which are "all day", and have dates in the range.

I'm not sure if this is simpler or not.

Particularly, although it's conceptually simpler, paging/ordering is probably even messier. Paging/ordering is simpler if we have a single total order relation across all events, even if the order isn't exactly correct in some timezones.

We can derive the correct total order like this:

epoch + IF(isAllDay, viewerOffsetFromGMT, 0)

...which can fix ordering/paging bugs, but MySQL can't use keys to execute this. It's fine to use this to page through events inside a keyable range, though.

Anyway, don't deal with this in v0 and we'll accept that "All Day" events slide around a bit for now.

Can't forget the javascript for the time controls.

Not sure if this can be reproduced on your side but the first all-day event I attempted to create on our instance (it was multi-day as well) gave me an "invalid timezone" exception. Apparently "GMT+12" was attempted to be used. I went to try again and succeeded that time.

I stand corrected. This still occurs for all-day events.

Specific error:

DateTimeZone::__construct(): Unknown or bad timezone (GMT+12)

@mbishopim3 can you try again with my last revision for this? Changed (GMT + 12) to actually be a timezone php knows about.