Skip to content

Instantly share code, notes, and snippets.

@andrasguseo
Last active November 1, 2019 21:51
Show Gist options
  • Save andrasguseo/c895e4a7755055c18148b5bbd482c1dd to your computer and use it in GitHub Desktop.
Save andrasguseo/c895e4a7755055c18148b5bbd482c1dd to your computer and use it in GitHub Desktop.
Modify timezone and time when importing with EA (The Events Calendar)
<?php
/*
* Description: Modifies the timezone and the time of imported events, if the source
* feed timezone is UTC
*
* Usage: Copy the snippet into your theme's (preferably child theme's) functions.php file.
* Modify the URL and the timezone at the end of the code based on your needs
* Timzone name list: the TZ* column on this page
* https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
*
* Version: 1.1
* Plugins: The Events Calendar (Event Aggregator)
* Author: Barry Hughes, Andras Guseo
* Last updated: January 17, 2018
*
* Changelog:
* Version 1.1 (January 17, 2018)
* - Fix: The time for all day events is not changed, but the timezone is still adjusted
*
* Version 1.0 (November 3, 2017)
* - Initial release
*/
class Imported_Events_Timezone_Modifier {
protected $source;
protected $target_timezone;
public function __construct( $source, $target_timezone ) {
$this->source = $source;
$this->target_timezone = $target_timezone;
}
public function __invoke( $event, $record ) {
# Only run if the event is being imported from the specified source
if ( $this->source === null || $this->source === $record->meta['source'] ) {
add_action(
'tribe_events_update_meta',
[ $this, 'post_creation' ]
);
}
return $event;
}
public function post_creation( $event_id ) {
# Run once only
remove_action(
'tribe_events_update_meta',
[ $this, 'post_creation' ]
);
// Check if it's an all day event
$allday = get_post_meta( $event_id, '_EventAllDay', true );
// If not all day, then adjust times
if ( $allday != "yes" ) {
$new_start_date = $this->convert( get_post_meta( $event_id, '_EventStartDateUTC', true ) );
$new_end_date = $this->convert( get_post_meta( $event_id, '_EventEndDateUTC', true ) );
}
// Update time
if ( $new_start_date && $new_end_date ) {
update_post_meta( $event_id, '_EventStartDate', $new_start_date );
update_post_meta( $event_id, '_EventEndDate', $new_end_date );
}
// Update timezone for all events
update_post_meta( $event_id, '_EventTimezone', $this->target_timezone );
}
protected function convert( $datetime ) {
try {
$datetime = new DateTime( $datetime );
$datetime->setTimezone( new DateTimeZone( 'UTC' ) );
$datetime->setTimezone( new DateTimeZone( $this->target_timezone ) );
return $datetime->format( Tribe__Date_Utils::DBDATETIMEFORMAT );
}
catch ( Exception $e ) {
return false;
}
}
}
function modify_imported_event_timezones( $source_feed, $target_timezone ) {
$modifier = new Imported_Events_Timezone_Modifier( $source_feed, $target_timezone );
add_filter( 'tribe_aggregator_before_insert_event', $modifier, 10, 2 );
}
# Set the first param to null (without quotation marks) to operate on all import sources.
# Update the second param to the desired timezone (it must be
# a valid timezone supported and understood by your PHP runtime).
modify_imported_event_timezones(
null,
'America/New_York'
);
# If you want to modify one feed only, then like this:
# modify_imported_event_timezones(
# 'https://domain.com/events/main-calendar.ics/',
# 'America/New_York'
# );
# If you have a second feed which you want to import with a different timezone then repeat
# modify_imported_event_timezones(
# 'https://domain.com/crm/events/party-calendar.ics/',
# 'America/Los_Angeles'
# );
@KZeni
Copy link

KZeni commented Nov 1, 2019

After coming across a hangup on a site where events were being updated from the remote source & then saw that the UTC times were being re-introduced when that happened (per the "Event Update Authority" imports setting allowing updates to be made to existing events [in case a time is changed, description is updated, etc.]), I'd suggest changing:

    add_filter( 'tribe_aggregator_before_insert_event', $modifier, 10, 2 );

to instead be:

    add_filter( 'tribe_aggregator_before_insert_event', $modifier, 10, 2 ); // Newly added events
    add_filter( 'tribe_aggregator_before_update_event', $modifier, 10, 2 ); // Already existing events being updated

Really, it's just adding the hook for events being updated as well as ones that are being added for the first time. Your same code works for both and it accounts for correcting the times to the specified timezone in either scenario (since there is a direct fork in the event aggregators code which determines which of these two filters are used [it sees if the event exists already or not]).

Thanks for the great code, and I'd be happy to see this addition included for future use/reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment