$timezone "; $schedule_text = $schedule_text . $timezone_text; } return $schedule_text; } /** * Returns the timezone string for the specified event (if null it assumes the * current event where that can be determined). * * If no timezone has explicitly been set for the event, it returns the global * WordPress timezone string. * * @param int|null $event_id * * @return string */ public static function get_event_timezone_string( $event_id = null ) { $event_id = Tribe__Events__Main::postIdHelper( $event_id ); $tzstring = get_post_meta( $event_id, '_EventTimezone', true ); return $tzstring ? $tzstring : self::wp_timezone_string(); } /** * Returns the event's timezone abbreviation if it can be determined, or else * falls back on the full timezone string/offset text (again, if known - if it * is not it will assume the global WP timezone setting). * * @param int|null $event_id * * @return string */ public static function get_event_timezone_abbr( $event_id = null ) { $abbr = get_post_meta( $event_id, '_EventTimezoneAbbr', true ); if ( empty( $abbr ) ) { $timezone_string = self::get_event_timezone_string( $event_id ); $date = tribe_get_start_date( $event_id, true, Tribe__Date_Utils::DBDATETIMEFORMAT ); $abbr = self::abbr( $date, $timezone_string ); } return empty( $abbr ) ? $timezone_string : $abbr; } /** * Returns the current site-wide timezone string. * * Based on the core WP code found in wp-admin/options-general.php. * * @return string */ public static function wp_timezone_string() { $current_offset = get_option( 'gmt_offset' ); $tzstring = get_option( 'timezone_string' ); // Return the timezone string if already set if ( ! empty( $tzstring ) ) { return $tzstring; } // Otherwise return the UTC offset if ( 0 == $current_offset ) { return 'UTC+0'; } elseif ( $current_offset < 0 ) { return 'UTC' . $current_offset; } return 'UTC+' . $current_offset; } /** * Returns the current site-wide timezone string abbreviation, if it can be * determined or falls back on the full timezone string/offset text. * * @param string $date * * @return string */ public static function wp_timezone_abbr( $date ) { $abbr = get_transient( 'tribe_events_wp_timezone_abbr' ); if ( empty( $abbr ) ) { $timezone_string = self::wp_timezone_string(); $abbr = self::abbr( $date, $timezone_string ); set_transient( 'tribe_events_wp_timezone_abbr', $abbr ); } return empty( $abbr ) ? $timezone_string : $abbr; } /** * Tried to convert the provided $datetime to UTC from the timezone represented by $tzstring. * * Though the usual range of formats are allowed, $datetime ordinarily ought to be something * like the "Y-m-d H:i:s" format (ie, no timezone information). If it itself contains timezone * data, the results may be unexpected. * * In those cases where the conversion fails to take place, the $datetime string will be * returned untouched. * * @param string $datetime * @param string $tzstring * * @return string */ public static function to_utc( $datetime, $tzstring ) { if ( self::is_utc_offset( $tzstring ) ) { return self::apply_offset( $datetime, $tzstring, true ); } $local = self::get_timezone( $tzstring ); $utc = self::get_timezone( 'UTC' ); $new_datetime = date_create( $datetime, $local ); if ( $new_datetime && $new_datetime->setTimezone( $utc ) ) { return $new_datetime->format( Tribe__Date_Utils::DBDATETIMEFORMAT ); } // Fallback to the unmodified datetime if there was a failure during conversion return $datetime; } /** * Tries to convert the provided $datetime to the timezone represented by $tzstring. * * This is the sister function of self::to_utc() - please review the docs for that method * for more information. * * @param string $datetime * @param string $tzstring * * @return string */ public static function to_tz( $datetime, $tzstring ) { if ( self::is_utc_offset( $tzstring ) ) { return self::apply_offset( $datetime, $tzstring ); } $local = self::get_timezone( $tzstring ); $utc = self::get_timezone( 'UTC' ); $new_datetime = date_create( $datetime, $utc ); if ( $new_datetime && $new_datetime->setTimezone( $local ) ) { return $new_datetime->format( Tribe__Date_Utils::DBDATETIMEFORMAT ); } // Fallback to the unmodified datetime if there was a failure during conversion return $datetime; } /** * Tests to see if the timezone string is a UTC offset, ie "UTC+2". * * @param string $timezone * * @return bool */ public static function is_utc_offset( $timezone ) { $timezone = trim( $timezone ); return ( 0 === strpos( $timezone, 'UTC' ) && strlen( $timezone ) > 3 ); } /** * @param string $datetime * @param mixed $offset (string or numeric offset) * @param bool $invert = false * * @return string */ public static function apply_offset( $datetime, $offset, $invert = false ) { // Normalize $offset = strtolower( trim( $offset ) ); // Strip any leading "utc" text if set if ( 0 === strpos( $offset, 'utc' ) ) { $offset = substr( $offset, 3 ); } // It's possible no adjustment will be needed if ( 0 === $offset ) { return $datetime; } // Convert the offset to minutes for easier handling of fractional offsets $offset = (int) ( $offset * 60 ); // Invert the offset? Useful for stripping an offset that has already been applied if ( $invert ) { $offset *= -1; } if ( $offset > 0 ) { $offset = '+' . $offset; } $offset = $offset . ' minutes'; $offset_datetime = date_create( $datetime ); if ( $offset_datetime && $offset_datetime->modify( $offset ) ) { return $offset_datetime->format( Tribe__Date_Utils::DBDATETIMEFORMAT ); } return $datetime; } /** * Returns a timestamp for the event start date that can be passed to tribe_format_date() * in order to produce the time in the correct timezone. * * @param int $event_id * @param string $timezone * * @return int */ public static function event_start_timestamp( $event_id, $timezone = null ) { return self::get_event_timestamp( $event_id, 'Start', $timezone ); } /** * Returns a timestamp for the event end date that can be passed to tribe_format_date() * in order to produce the time in the correct timezone. * * @param int $event_id * @param string $timezone * * @return int */ public static function event_end_timestamp( $event_id, $timezone = null ) { return self::get_event_timestamp( $event_id, 'End', $timezone ); } /** * Returns a timestamp for the event date that can be passed to tribe_format_date() * in order to produce the time in the correct timezone. * * @param int $event_id * @param string $type (expected to be 'Start' or 'End') * @param string $timezone * * @return int */ protected static function get_event_timestamp( $event_id, $type = 'Start', $timezone = null ) { $event = get_post( Tribe__Events__Main::postIdHelper( $event_id ) ); $event_tz = get_post_meta( $event->ID, '_EventTimezone', true ); $site_tz = self::wp_timezone_string(); if ( null === $timezone ) { $timezone = self::mode(); } // Should we use the event specific timezone or the site-wide timezone? $use_event_tz = self::EVENT_TIMEZONE === $timezone; $use_site_tz = self::SITE_TIMEZONE === $timezone; // Determine if the event timezone and site timezone the same *or* if the event does not have timezone // information (in which case, we'll assume the event time inherits the site timezone) $site_zone_is_event_zone = ( $event_tz === $site_tz || empty( $event_tz ) ); // If the event-specific timezone is suitable, we can obtain it without any conversion work if ( $use_event_tz || ( $use_site_tz && $site_zone_is_event_zone ) ) { $datetime = isset( $event->{"Event{$type}Date"} ) ? $event->{"Event{$type}Date"} : get_post_meta( $event->ID, "_Event{$type}Date", true ); return strtotime( $datetime ); } // Otherwise lets load the event's UTC time and convert it $datetime = isset( $event->{"Event{$type}DateUTC"} ) ? $event->{"Event{$type}DateUTC"} : get_post_meta( $event->ID, "_Event{$type}DateUTC", true ); $tzstring = ( self::SITE_TIMEZONE === $timezone ) ? self::wp_timezone_string() : $timezone; $localized = self::to_tz( $datetime, $tzstring ); return strtotime( $localized ); } /** * Accepts a unix timestamp and adjusts it so that when it is used to consitute * a new datetime string, that string reflects the designated timezone. * * @param string $unix_timestamp * @param string $tzstring * * @return string */ public static function adjust_timestamp( $unix_timestamp, $tzstring ) { try { $local = self::get_timezone( $tzstring ); $datetime = date_create_from_format( 'U', $unix_timestamp )->format( Tribe__Date_Utils::DBDATETIMEFORMAT ); return date_create_from_format( 'Y-m-d H:i:s', $datetime, $local )->getTimestamp(); } catch( Exception $e ) { return $unix_timestamp; } } /** * Returns a DateTimeZone object matching the representation in $tzstring where * possible, or else representing UTC (or, in the worst case, false). * * If optional parameter $with_fallback is true, which is the default, then in * the event it cannot find/create the desired timezone it will try to return the * UTC DateTimeZone before bailing. * * @param string $tzstring * @param bool $with_fallback = true * * @return DateTimeZone|false */ public static function get_timezone( $tzstring, $with_fallback = true ) { if ( isset( self::$timezones[ $tzstring ] ) ) { return self::$timezones[ $tzstring ]; } try { self::$timezones[ $tzstring ] = new DateTimeZone( $tzstring ); return self::$timezones[ $tzstring ]; } catch ( Exception $e ) { if ( $with_fallback ) { return self::get_timezone( 'UTC', true ); } } return false; } /** * Returns a string representing the timezone/offset currently desired for * the display of dates and times. * * @return string */ public static function mode() { $mode = self::EVENT_TIMEZONE; if ( 'site' === tribe_get_option( 'tribe_events_timezone_mode' ) ) { $mode = self::SITE_TIMEZONE; } return apply_filters( 'tribe_events_current_display_timezone', $mode ); } /** * Confirms if the current timezone mode matches the $possible_mode. * * @param string $possible_mode * * @return bool */ public static function is_mode( $possible_mode ) { return $possible_mode === self::mode(); } /** * Attempts to provide the correct timezone abbreviation for the provided timezone string * on the date given (and so should account for daylight saving time, etc). * * @param string $date * @param string $timezone_string * * @return string */ public static function abbr( $date, $timezone_string ) { try { return date_create( $date, new DateTimeZone( $timezone_string ) )->format( 'T' ); } catch ( Exception $e ) { return ''; } } }