Events Plugin 📆

Timezones update

I’ve simplified the way timezones are handled.

Event creation, editing and display

For creating, editing and displaying an event, the timezone is set according to this hierarchy:

// Start with the user's timezone, guessed by momentjs.
let timezone = moment.tz.guess();

// If a default timezone is set in the site setting use that instead.
const defaultTimezone = Discourse.SiteSettings.events_default_timezone;
if (defaultTimezone) {
  timezone = defaultTimezone;
}

// If the event has a custom timezone use that instead.
if (event['timezone']) {
  timezone = event['timezone'];
}

return timezone;

The decision on whether or not to display a timezone label next to a datetime is determined according to this logic:

const defaultTimezone = Discourse.SiteSettings.events_default_timezone;
const standardTimezone = defaultTimezone || moment.tz.guess();

if (!allDay && event['timezone'] && event['timezone'] !== standardTimezone) {
  dateString += `, ${timezoneLabel(event['timezone'])}`;
}

Basically, if the event is not an all day event and has a custom timezone that is different from the standard timezone (either the site setting or the user’s own timezone), then the timezone is displayed.

Zone list

I’ve also updated the timezone list (used for both the default timezone setting and the custom timezone input in event creation / editing modal) to filter duplicate values in the ActiveSupport::TimeZone::MAPPING. This simplifies the selection of zones (e.g. prevents issues with having objects with duplicate keys in a combo-box)

timezones = ActiveSupport::TimeZone::MAPPING
zone_map = []
remove_zones = []

# Remove the duplicate zones where the label doesn't include the city in the zone.
timezones.each do |k, v|
  if zone_map.include?(v)
    duplicates = timezones.select { |key, val| val === v }
    remove = duplicates.select{ |key, val| !val.include?(key) }
    remove_zones.push(*remove.keys)
  end

  zone_map.push(v)
end

timezones.except!(*remove_zones)

Basically, this means that when you have two or more “Readable” labels referring to the same IANA zone such as

"Edinburgh" => "Europe/London",
"London" => "Europe/London"

The zone with a label that does not match in the city in the IANA zone is removed. In this case Edinburgh would be removed.

Emails

The timezone of event times in emails is set according to this logic:

event_timezone = SiteSetting.events_default_timezone
event_timezone = event[:timezone] if event[:timezone].present?

i.e. Start with the default timezone, then use the custom event timezone if one is used.

I’ve also added a setting that toggles the display of timezones in event emails: events_emails_include_timezones. Default is true. The event time in the email is still going to be localised according to the logic above regardless of this setting.

@ChrisBeach Amongst other things, I hope this addresses your various timezone issues.

https://github.com/angusmcleod/discourse-events/commit/8fd960e2c3e65a0996155bead509891a04748004

9 Likes