Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 52.14.234.146
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/wavevlvu/misswavenigeria.com/wp-content/plugins/event-tickets/common/src/Tribe/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/wavevlvu/misswavenigeria.com/wp-content/plugins/event-tickets/common/src/Tribe/Date_Utils.php
<?php
/**
 * Date utility functions used throughout TEC + Addons
 */

use Tribe\Utils\Date_I18n;
use Tribe\Utils\Date_I18n_Immutable;

// Don't load directly

if ( ! defined( 'ABSPATH' ) ) {
	die( '-1' );
}

if ( ! class_exists( 'Tribe__Date_Utils' ) ) {
	class Tribe__Date_Utils {
		// Default formats, they are overridden by WP options or by arguments to date methods
		const DATEONLYFORMAT        = 'F j, Y';
		const TIMEFORMAT            = 'g:i A';
		const HOURFORMAT            = 'g';
		const MINUTEFORMAT          = 'i';
		const MERIDIANFORMAT        = 'A';
		const DBDATEFORMAT          = 'Y-m-d';
		const DBDATETIMEFORMAT      = 'Y-m-d H:i:s';
		const DBTZDATETIMEFORMAT    = 'Y-m-d H:i:s O';
		const DBTIMEFORMAT          = 'H:i:s';
		const DBYEARMONTHTIMEFORMAT = 'Y-m';

		/**
		 * Default datepicker format index.
		 *
		 * @since 4.11.0.1
		 *
		 * @var int
		 */
		private static $default_datepicker_format_index = 1;

		private static $localized_months_full = [];
		private static $localized_months_short = [];
		private static $localized_weekdays = [];
		private static $localized_months = [];

		/**
		 * Get the datepickerFormat index.
		 *
		 * @since 4.11.0.1
		 *
		 * @return int
		 */
		public static function get_datepicker_format_index() {
			/**
			 * Filter the datepickerFormat index.
			 *
			 * @since 4.11.0.1
			 *
			 * @param int $format_index Index of datepickerFormat.
			 */
			return apply_filters( 'tribe_datepicker_format_index', tribe_get_option( 'datepickerFormat', static::$default_datepicker_format_index ) );
		}

		/**
		 * Try to format a Date to the Default Datepicker format
		 *
		 * @since  4.5.12
		 *
		 * @param  string      $date       Original Date that came from a datepicker
		 * @param  string|int  $datepicker Datepicker format
		 * @return string
		 */
		public static function maybe_format_from_datepicker( $date, $datepicker = null ) {
			if ( ! is_numeric( $datepicker ) ) {
				$datepicker = self::get_datepicker_format_index();
			}

			if ( is_numeric( $datepicker ) ) {
				$datepicker = self::datepicker_formats( $datepicker );
			}

			$default_datepicker = self::datepicker_formats( 1 );

			// If the current datepicker is the default we don't care
			if ( $datepicker === $default_datepicker ) {
				return $date;
			}

			return self::datetime_from_format( $datepicker, $date );
		}

		/**
		 * Get the datepicker format, that is used to translate the option from the DB to a string
		 *
		 * @param  int $translate The db Option from datepickerFormat
		 * @return string|array            If $translate is not set returns the full array, if not returns the `Y-m-d`
		 */
		public static function datepicker_formats( $translate = null ) {

			// The datepicker has issues when a period separator and no leading zero is used. Those formats are purposefully omitted.
			$formats = [
				0     => 'Y-m-d',
				1     => 'n/j/Y',
				2     => 'm/d/Y',
				3     => 'j/n/Y',
				4     => 'd/m/Y',
				5     => 'n-j-Y',
				6     => 'm-d-Y',
				7     => 'j-n-Y',
				8     => 'd-m-Y',
				9     => 'Y.m.d',
				10    => 'm.d.Y',
				11    => 'd.m.Y',
				'm0'  => 'Y-m',
				'm1'  => 'n/Y',
				'm2'  => 'm/Y',
				'm3'  => 'n/Y',
				'm4'  => 'm/Y',
				'm5'  => 'n-Y',
				'm6'  => 'm-Y',
				'm7'  => 'n-Y',
				'm8'  => 'm-Y',
				'm9'  => 'Y.m',
				'm10' => 'm.Y',
				'm11' => 'm.Y',
			];

			if ( is_null( $translate ) ) {
				return $formats;
			}

			return isset( $formats[ $translate ] ) ? $formats[ $translate ] : $formats[ static::get_datepicker_format_index() ];
		}

		/**
		 * As PHP 5.2 doesn't have a good version of `date_parse_from_format`, this is how we deal with
		 * possible weird datepicker formats not working
		 *
		 * @param  string $format The weird format you are using
		 * @param  string $date   The date string to parse
		 *
		 * @return string         A DB formated Date, includes time if possible
		 */
		public static function datetime_from_format( $format, $date ) {
			// Reverse engineer the relevant date formats
			$keys = [
				// Year with 4 Digits
				'Y' => [ 'year', '\d{4}' ],

				// Year with 2 Digits
				'y' => [ 'year', '\d{2}' ],

				// Month with leading 0
				'm' => [ 'month', '\d{2}' ],

				// Month without the leading 0
				'n' => [ 'month', '\d{1,2}' ],

				// Month ABBR 3 letters
				'M' => [ 'month', '[A-Z][a-z]{2}' ],

				// Month Name
				'F' => [ 'month', '[A-Z][a-z]{2,8}' ],

				// Day with leading 0
				'd' => [ 'day', '\d{2}' ],

				// Day without leading 0
				'j' => [ 'day', '\d{1,2}' ],

				// Day ABBR 3 Letters
				'D' => [ 'day', '[A-Z][a-z]{2}' ],

				// Day Name
				'l' => [ 'day', '[A-Z][a-z]{5,8}' ],

				// Hour 12h formatted, with leading 0
				'h' => [ 'hour', '\d{2}' ],

				// Hour 24h formatted, with leading 0
				'H' => [ 'hour', '\d{2}' ],

				// Hour 12h formatted, without leading 0
				'g' => [ 'hour', '\d{1,2}' ],

				// Hour 24h formatted, without leading 0
				'G' => [ 'hour', '\d{1,2}' ],

				// Minutes with leading 0
				'i' => [ 'minute', '\d{2}' ],

				// Seconds with leading 0
				's' => [ 'second', '\d{2}' ],
			];

			$date_regex = "/{$keys['Y'][1]}-{$keys['m'][1]}-{$keys['d'][1]}( {$keys['H'][1]}:{$keys['i'][1]}:{$keys['s'][1]})?$/";

			// if the date is already in Y-m-d or Y-m-d H:i:s, just return it
			if ( preg_match( $date_regex, $date ) ) {
				return $date;
			}


			// Convert format string to regex
			$regex = '';
			$chars = str_split( $format );
			foreach ( $chars as $n => $char ) {
				$last_char = isset( $chars[ $n - 1 ] ) ? $chars[ $n - 1 ] : '';
				$skip_current = '\\' == $last_char;
				if ( ! $skip_current && isset( $keys[ $char ] ) ) {
					$regex .= '(?P<' . $keys[ $char ][0] . '>' . $keys[ $char ][1] . ')';
				} elseif ( '\\' == $char ) {
					$regex .= $char;
				} else {
					$regex .= preg_quote( $char );
				}
			}

			$dt = [];

			// Now try to match it
			if ( preg_match( '#^' . $regex . '$#', $date, $dt ) ) {
				// Remove unwanted Indexes
				foreach ( $dt as $k => $v ) {
					if ( is_int( $k ) ) {
						unset( $dt[ $k ] );
					}
				}

				// We need at least Month + Day + Year to work with
				if ( ! checkdate( $dt['month'], $dt['day'], $dt['year'] ) ) {
					return false;
				}
			} else {
				return false;
			}

			$dt['month'] = str_pad( $dt['month'], 2, '0', STR_PAD_LEFT );
			$dt['day'] = str_pad( $dt['day'], 2, '0', STR_PAD_LEFT );

			$formatted = '{year}-{month}-{day}' . ( isset( $dt['hour'], $dt['minute'], $dt['second'] ) ? ' {hour}:{minute}:{second}' : '' );
			foreach ( $dt as $key => $value ) {
				$formatted = str_replace( '{' . $key . '}', $value, $formatted );
			}

			return $formatted;
		}

		/**
		 * Returns the date only.
		 *
		 * @param int|string  $date         The date (timestamp or string). If an empty or null date is provided it will default to 'now'.
		 * @param bool        $is_timestamp Whether or not $date is in timestamp format.
		 * @param string|null $format       The format used.
		 *
		 * @return string The date only in DB format.
		 */
		public static function date_only( $date, $is_timestamp = false, $format = null ) {
			$date = $is_timestamp ? $date : strtotime( $date ?? 'now' );

			if ( is_null( $format ) ) {
				$format = self::DBDATEFORMAT;
			}

			return date( $format, $date );
		}

		/**
		 * Returns as string the nearest half a hour for a given valid string datetime.
		 *
		 * @since  4.10.2
		 *
		 * @param string $date Valid DateTime string.
		 *
		 * @return string Rounded datetime string
		 */
		public static function round_nearest_half_hour( $date ) {
			$date_object = static::build_date_object( $date );
			$rounded_minutes = floor( $date_object->format( 'i' ) / 30 ) * 30;

			return $date_object->format( 'Y-m-d H:' ) . $rounded_minutes . ':00';
		}

		/**
		 * Returns the time only.
		 *
		 * @param string $date The date.
		 *
		 * @return string The time only in DB format.
		 */
		public static function time_only( $date ) {
			$date = is_numeric( $date ) ? $date : strtotime( $date );
			return date( self::DBTIMEFORMAT, $date );
		}

		/**
		 * Returns the hour only.
		 *
		 * @param string $date The date.
		 *
		 * @return string The hour only.
		 */
		public static function hour_only( $date ) {
			$date = is_numeric( $date ) ? $date : strtotime( $date );
			return date( self::HOURFORMAT, $date );
		}

		/**
		 * Returns the minute only.
		 *
		 * @param string $date The date.
		 *
		 * @return string The minute only.
		 */
		public static function minutes_only( $date ) {
			$date = is_numeric( $date ) ? $date : strtotime( $date );
			return date( self::MINUTEFORMAT, $date );
		}

		/**
		 * Returns the meridian (am or pm) only.
		 *
		 * @param string $date The date.
		 *
		 * @return string The meridian only in DB format.
		 */
		public static function meridian_only( $date ) {
			$date = is_numeric( $date ) ? $date : strtotime( $date );
			return date( self::MERIDIANFORMAT, $date );
		}

		/**
		 * Returns the number of seconds (absolute value) between two dates/times.
		 *
		 * @param string $date1 The first date.
		 * @param string $date2 The second date.
		 *
		 * @return int The number of seconds between the dates.
		 */
		public static function time_between( $date1, $date2 ) {
			return abs( strtotime( $date1 ) - strtotime( $date2 ) );
		}

		/**
		 * The number of days between two arbitrary dates.
		 *
		 * @param string $date1 The first date.
		 * @param string $date2 The second date.
		 *
		 * @return int The number of days between two dates.
		 */
		public static function date_diff( $date1, $date2 ) {
			// Get number of days between by finding seconds between and dividing by # of seconds in a day
			$days = self::time_between( $date1, $date2 ) / ( 60 * 60 * 24 );

			return $days;
		}

		/**
		 * Returns the last day of the month given a php date.
		 *
		 * @param int $timestamp THe timestamp.
		 *
		 * @return string The last day of the month.
		 */
		public static function get_last_day_of_month( $timestamp ) {
			$curmonth  = date( 'n', $timestamp );
			$curYear   = date( 'Y', $timestamp );
			$nextmonth = mktime( 0, 0, 0, $curmonth + 1, 1, $curYear );
			$lastDay   = strtotime( date( self::DBDATETIMEFORMAT, $nextmonth ) . ' - 1 day' );

			return date( 'j', $lastDay );
		}

		/**
		 * Returns true if the timestamp is a weekday.
		 *
		 * @param int $curDate A timestamp.
		 *
		 * @return bool If the timestamp is a weekday.
		 */
		public static function is_weekday( $curdate ) {
			return in_array( date( 'N', $curdate ), [ 1, 2, 3, 4, 5 ] );
		}

		/**
		 * Returns true if the timestamp is a weekend.
		 *
		 * @param int $curDate A timestamp.
		 *
		 * @return bool If the timestamp is a weekend.
		 */
		public static function is_weekend( $curdate ) {
			return in_array( date( 'N', $curdate ), [ 6, 7 ] );
		}

		/**
		 * Gets the last day of the week in a month (ie the last Tuesday).  Passing in -1 gives you the last day in the month.
		 *
		 * @param int $curdate     A timestamp.
		 * @param int $day_of_week The index of the day of the week.
		 *
		 * @return int The timestamp of the date that fits the qualifications.
		 */
		public static function get_last_day_of_week_in_month( $curdate, $day_of_week ) {
			$nextdate = mktime( date( 'H', $curdate ), date( 'i', $curdate ), date( 's', $curdate ), date( 'n', $curdate ), self::get_last_day_of_month( $curdate ), date( 'Y', $curdate ) );// phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date

			while ( date( 'N', $nextdate ) != $day_of_week && $day_of_week != - 1 ) {
				$nextdate = strtotime( date( self::DBDATETIMEFORMAT, $nextdate ) . ' - 1 day' );
			}

			return $nextdate;
		}

		/**
		 * Gets the first day of the week in a month (ie the first Tuesday).
		 *
		 * @param int $curdate     A timestamp.
		 * @param int $day_of_week The index of the day of the week.
		 *
		 * @return int The timestamp of the date that fits the qualifications.
		 */
		public static function get_first_day_of_week_in_month( $curdate, $day_of_week ) {
			$nextdate = mktime( 0, 0, 0, date( 'n', $curdate ), 1, date( 'Y', $curdate ) );

			while ( ! ( $day_of_week > 0 && date( 'N', $nextdate ) == $day_of_week ) &&
					! ( $day_of_week == - 1 && self::is_weekday( $nextdate ) ) &&
					! ( $day_of_week == - 2 && self::is_weekend( $nextdate ) ) ) {
				$nextdate = strtotime( date( self::DBDATETIMEFORMAT, $nextdate ) . ' + 1 day' );
			}

			return $nextdate;
		}

		/**
		 * From http://php.net/manual/en/function.date.php
		 *
		 * @param int $number A number.
		 *
		 * @return string The ordinal for that number.
		 */
		public static function number_to_ordinal( $number ) {
			$output = $number . ( ( ( strlen( $number ) > 1 ) && ( substr( $number, - 2, 1 ) == '1' ) ) ?
					'th' : date( 'S', mktime( 0, 0, 0, 0, substr( $number, - 1 ), 0 ) ) );

			return apply_filters( 'tribe_events_number_to_ordinal', $output, $number );
		}

		/**
		 * check if a given string is a timestamp
		 *
		 * @param $timestamp
		 *
		 * @return bool
		 */
		public static function is_timestamp( $timestamp ) {
			if ( is_numeric( $timestamp ) && (int) $timestamp == $timestamp && date( 'U', $timestamp ) == $timestamp ) {
				return true;
			}

			return false;
		}

		/**
		 * Accepts a string representing a date/time and attempts to convert it to
		 * the specified format, returning an empty string if this is not possible.
		 *
		 * @since 5.1.5 Make use of `wp_date` for i18n.
		 * @since 5.2.2 Adding timezone param.
		 *
		 * @param string|int  $dt_string  The date or timestamp to be converted.
		 * @param string      $new_format The date format to convert to.
		 * @param null|string $timezone   Optional timezone the date string is in.
		 *
		 * @return string
		 */
		public static function reformat( $dt_string, $new_format, $timezone = null ): string {
			$timestamp = $dt_string;
			$timezone  = $timezone ? new DateTimeZone( $timezone ) : wp_timezone();
			if ( ! self::is_timestamp( $timestamp ) ) {
				$date = new DateTime( $timestamp, $timezone );
			} else {
				$date = DateTime::createFromFormat( 'U', $timestamp );
				$date->setTimezone( $timezone );
			}

			return $date->format( $new_format );
		}

		/**
		 * Accepts a numeric offset (such as "4" or "-6" as stored in the gmt_offset
		 * option) and converts it to a strtotime() style modifier that can be used
		 * to adjust a DateTime object, etc.
		 *
		 * @param $offset
		 *
		 * @return string
		 */
		public static function get_modifier_from_offset( $offset ) {
			$modifier = '';
			$offset   = (float) $offset;

			// Separate out hours, minutes, polarity
			$hours    = (int) $offset;
			$minutes  = (int) ( ( $offset - $hours ) * 60 );
			$polarity = ( $offset >= 0 ) ? '+' : '-';

			// Correct hours and minutes to positive values
			if ( $hours < 0 )   $hours *= -1;
			if ( $minutes < 0 ) $minutes *= -1;

			// Form the modifier string
			if ( $hours >= 0 )  $modifier  = "$polarity $hours hours ";
			if ( $minutes > 0 ) $modifier .= "$minutes minutes";

			return $modifier;
		}

		/**
		 * Returns the weekday of the 1st day of the month in
		 * "w" format (ie, Sunday is 0 and Saturday is 6) or
		 * false if this cannot be established.
		 *
		 * @param  mixed $month
		 * @return int|bool
		 */
		public static function first_day_in_month( $month ) {
			try {
				$date  = new DateTime( $month );
				$day_1 = new DateTime( $date->format( 'Y-m-01 ' ) );
				return $day_1->format( 'w' );
			}
			catch ( Exception $e ) {
				return false;
			}
		}

		/**
		 * Returns the weekday of the last day of the month in
		 * "w" format (ie, Sunday is 0 and Saturday is 6) or
		 * false if this cannot be established.
		 *
		 * @param  mixed $month
		 * @return int|bool
		 */
		public static function last_day_in_month( $month ) {
			try {
				$date  = new DateTime( $month );
				$day_1 = new DateTime( $date->format( 'Y-m-t' ) );
				return $day_1->format( 'w' );
			}
			catch ( Exception $e ) {
				return false;
			}
		}

		/**
		 * Returns the day of the week the week ends on, expressed as a "w" value
		 * (ie, Sunday is 0 and Saturday is 6).
		 *
		 * @param  int $week_starts_on
		 *
		 * @return int
		 */
		public static function week_ends_on( $week_starts_on ) {
			if ( --$week_starts_on < 0 ) $week_starts_on = 6;
			return $week_starts_on;
		}

		/**
		 * Helper method to convert EventAllDay values to a boolean
		 *
		 * @param mixed $all_day_value Value to check for "all day" status. All day values: (true, 'true', 'TRUE', 'yes')
		 *
		 * @return boolean Is value considered "All Day"?
		 */
		public static function is_all_day( $all_day_value ) {
			$all_day_value = trim( $all_day_value );

			return (
				'true' === strtolower( $all_day_value )
				|| 'yes' === strtolower( $all_day_value )
				|| true === $all_day_value
				|| 1 == $all_day_value
			);
		}

		/**
		 * Determine if "now" is between two dates.
		 *
		 * @since 5.0.2
		 *
		 * @param string|DateTime|int $start_date A `strtotime` parsable string, a DateTime object or a timestamp.
		 * @param string|DateTime|int $end_date   A `strtotime` parsable string, a DateTime object or a timestamp.
		 * @param string|DateTime|int $now        A `strtotime` parsable string, a DateTime object or a timestamp. Defaults to 'now'.
		 *
		 * @return boolean Whether the current datetime (or passed "now") is between the passed start and end dates.
		 */
		public static function is_now( $start_date, $end_date, $now = 'now' ) : bool {
			$now        = self::build_date_object( $now );
			$start_date = self::build_date_object( $start_date );
			$end_date   = self::build_date_object( $end_date );

			// If the dates are identical, bail early.
			if ( $start_date === $end_date ) {
				return false;
			}

			// Handle dates passed out of chronological order.
			[ $start_date, $end_date ] = self::sort( [ $start_date, $end_date ] );

			// If span starts after now, return false.
			if ( $start_date > $now ) {
				return false;
			}

			// If span ends on or before now, return false.
			if ( $end_date <= $now ) {
				return false;
			}

			return true;
		}

		/**
		 * Sort an array of dates.
		 *
		 * @since 5.0.2
		 *
		 * @param mixed  $dates     A single array of dates, or dates passed as individual params.
		 *                          Individual dates can be a `strtotime` parsable string, a DateTime object or a timestamp.
		 * @param string $direction 'ASC' or 'DESC' for ascending/descending sorting. Defaults to 'ASC'.
		 *
		 * @return array<DateTime> A sorted array of DateTime objects.
		 */
		public static function sort( array $dates, string $direction = 'ASC' ) :array {
			// If we get passed a single array, break it out of the containing array.
			if ( is_array( $dates[0] ) ) {
				$dates = $dates[0];
			}

			// Ensure we're always dealing with date objects here.
			$dates = array_map(
				function( $date ) {
					return self::build_date_object( $date );
				},
				$dates
			);

			// If anything other than 'DESC' gets passed (or nothing) we sort ascending.
			if ( 'DESC' === $direction ) {
				rsort( $dates );
			} else {
				sort( $dates );
			}

			return $dates;
		}

		/**
		 * Given 2 datetime ranges, return whether the 2nd one occurs during the 1st one
		 * Note: all params should be unix timestamps
		 *
		 * @param integer $range_1_start timestamp for start of the first range
		 * @param integer $range_1_end timestamp for end of the first range
		 * @param integer $range_2_start timestamp for start of the second range
		 * @param integer $range_2_end timestamp for end of the second range
		 *
		 * @return bool
		 */
		public static function range_coincides( $range_1_start, $range_1_end, $range_2_start, $range_2_end ) {

			// Initialize the return value
			$range_coincides = false;

			/**
			 * conditions:
			 * range 2 starts during range 1 (range 2 start time is between start and end of range 1 )
			 * range 2 ends during range 1 (range 2 end time is between start and end of range 1 )
			 * range 2 encloses range 1 (range 2 starts before range 1 and ends after range 1)
			 */

			$range_2_starts_during_range_1 = $range_2_start >= $range_1_start && $range_2_start < $range_1_end;
			$range_2_ends_during_range_1   = $range_2_end > $range_1_start && $range_2_end <= $range_1_end;
			$range_2_encloses_range_1      = $range_2_start < $range_1_start && $range_2_end > $range_1_end;

			if ( $range_2_starts_during_range_1 || $range_2_ends_during_range_1 || $range_2_encloses_range_1 ) {
				$range_coincides = true;
			}

			return $range_coincides;

		}

		/**
		 * Converts a locally-formatted date to a unix timestamp. This is a drop-in
		 * replacement for `strtotime()`, except that where strtotime assumes GMT, this
		 * assumes local time (as described below). If a timezone is specified, this
		 * function defers to strtotime().
		 *
		 * If there is a timezone_string available, the date is assumed to be in that
		 * timezone, otherwise it simply subtracts the value of the 'gmt_offset'
		 * option.
		 *
		 * @see  strtotime()
		 * @uses get_option() to retrieve the value of 'gmt_offset'
		 *
		 * @param string $string A date/time string. See `strtotime` for valid formats
		 *
		 * @return int UNIX timestamp.
		 */
		public static function wp_strtotime( $string ) {
			// If there's a timezone specified, we shouldn't convert it
			try {
				$test_date = new DateTime( $string );
				if ( 'UTC' != $test_date->getTimezone()->getName() ) {
					return strtotime( $string );
				}
			} catch ( Exception $e ) {
				return strtotime( $string );
			}

			$cache = tribe( 'cache' );
			if ( ! isset( $cache['option_timezone_string'] ) ) {
				$cache['option_timezone_string'] = get_option( 'timezone_string' );
			}
			if ( ! isset( $cache['option_gmt_offset'] ) ) {
				$cache['option_gmt_offset'] = get_option( 'gmt_offset' );
			}

			$tz = $cache['option_timezone_string'];
			if ( ! empty( $tz ) ) {
				$date = date_create( $string, new DateTimeZone( $tz ) );
				if ( ! $date ) {
					return strtotime( $string );
				}
				$date->setTimezone( new DateTimeZone( 'UTC' ) );
				return $date->format( 'U' );
			} else {
				$offset = (float) $cache['option_gmt_offset'];
				$seconds = intval( $offset * HOUR_IN_SECONDS );
				$timestamp = strtotime( $string ) - $seconds;
				return $timestamp;
			}
		}

		/**
		 * Returns an array of localized full month names.
		 *
		 * @return array
		 */
		public static function get_localized_months_full() {
			global $wp_locale;

			if ( empty( self::$localized_months ) ) {
				self::build_localized_months();
			}

			if ( empty( self::$localized_months_full ) ) {
				self::$localized_months_full = [
					'January'   => self::$localized_months['full']['01'],
					'February'  => self::$localized_months['full']['02'],
					'March'     => self::$localized_months['full']['03'],
					'April'     => self::$localized_months['full']['04'],
					'May'       => self::$localized_months['full']['05'],
					'June'      => self::$localized_months['full']['06'],
					'July'      => self::$localized_months['full']['07'],
					'August'    => self::$localized_months['full']['08'],
					'September' => self::$localized_months['full']['09'],
					'October'   => self::$localized_months['full']['10'],
					'November'  => self::$localized_months['full']['11'],
					'December'  => self::$localized_months['full']['12'],
				];
			}

			return self::$localized_months_full;
		}

		/**
		 * Returns an array of localized short month names.
		 *
		 * @return array
		 */
		public static function get_localized_months_short() {
			global $wp_locale;

			if ( empty( self::$localized_months ) ) {
				self::build_localized_months();
			}

			if ( empty( self::$localized_months_short ) ) {
				self::$localized_months_short = [
					'Jan' => self::$localized_months['short']['01'],
					'Feb' => self::$localized_months['short']['02'],
					'Mar' => self::$localized_months['short']['03'],
					'Apr' => self::$localized_months['short']['04'],
					'May' => self::$localized_months['short']['05'],
					'Jun' => self::$localized_months['short']['06'],
					'Jul' => self::$localized_months['short']['07'],
					'Aug' => self::$localized_months['short']['08'],
					'Sep' => self::$localized_months['short']['09'],
					'Oct' => self::$localized_months['short']['10'],
					'Nov' => self::$localized_months['short']['11'],
					'Dec' => self::$localized_months['short']['12'],
				];
			}

			return self::$localized_months_short;
		}

		/**
		 * Returns an array of localized full week day names.
		 *
		 * @return array
		 */
		public static function get_localized_weekdays_full() {
			if ( empty( self::$localized_weekdays ) ) {
				self::build_localized_weekdays();
			}

			return self::$localized_weekdays['full'];
		}

		/**
		 * Returns an array of localized short week day names.
		 *
		 * @return array
		 */
		public static function get_localized_weekdays_short() {
			if ( empty( self::$localized_weekdays ) ) {
				self::build_localized_weekdays();
			}

			return self::$localized_weekdays['short'];
		}

		/**
		 * Returns an array of localized week day initials.
		 *
		 * @return array
		 */
		public static function get_localized_weekdays_initial() {
			if ( empty( self::$localized_weekdays ) ) {
				self::build_localized_weekdays();
			}

			return self::$localized_weekdays['initial'];
		}

		/**
		 * Builds arrays of localized full, short and initialized weekdays.
		 */
		private static function build_localized_weekdays() {
			global $wp_locale;

			for ( $i = 0; $i <= 6; $i++ ) {
				$day = $wp_locale->get_weekday( $i );
				self::$localized_weekdays['full'][ $i ]    = $day;
				self::$localized_weekdays['short'][ $i ]   = $wp_locale->get_weekday_abbrev( $day );
				self::$localized_weekdays['initial'][ $i ] = $wp_locale->get_weekday_initial( $day );
			}
		}

		/**
		 * Builds arrays of localized full and short months.
		 *
		 * @since 4.4.3
		 */
		private static function build_localized_months() {
			global $wp_locale;

			for ( $i = 1; $i <= 12; $i++ ) {
				$month_number = str_pad( $i, 2, '0', STR_PAD_LEFT );
				$month        = $wp_locale->get_month( $month_number );
				self::$localized_months['full'][ $month_number ]  = $month;
				self::$localized_months['short'][ $month_number ] = $wp_locale->get_month_abbrev( $month );
			}
		}

		/**
		 * Return a WP Locale weekday in the specified format
		 *
		 * @since 4.4.3
		 *
		 * @param int|string $weekday Day of week
		 * @param string $format Weekday format: full, weekday, initial, abbreviation, abbrev, abbr, short
		 *
		 * @return string
		 */
		public static function wp_locale_weekday( $weekday, $format = 'weekday' ) {
			$weekday = trim( $weekday );

			$valid_formats = [
				'full',
				'weekday',
				'initial',
				'abbreviation',
				'abbrev',
				'abbr',
				'short',
			];

			// if there isn't a valid format, bail without providing a localized string
			if ( ! in_array( $format, $valid_formats ) ) {
				return $weekday;
			}

			if ( empty( self::$localized_weekdays ) ) {
				self::build_localized_weekdays();
			}

			// if the weekday isn't numeric, we need to convert to numeric in order to
			// leverage self::localized_weekdays
			if ( ! is_numeric( $weekday ) ) {
				$days_of_week = [
					'Sun',
					'Mon',
					'Tue',
					'Wed',
					'Thu',
					'Fri',
					'Sat',
				];

				$day_index = array_search( ucwords( substr( $weekday, 0, 3 ) ), $days_of_week );

				if ( false === $day_index ) {
					return $weekday;
				}

				$weekday = $day_index;
			}

			switch ( $format ) {
				case 'initial':
					$type = 'initial';
					break;
				case 'abbreviation':
				case 'abbrev':
				case 'abbr':
				case 'short':
					$type = 'short';
					break;
				case 'weekday':
				case 'full':
				default:
					$type = 'full';
					break;
			}

			return self::$localized_weekdays[ $type ][ $weekday ];
		}

		/**
		 * Return a WP Locale month in the specified format
		 *
		 * @since 4.4.3
		 *
		 * @param int|string $month Month of year
		 * @param string $format Month format: full, month, abbreviation, abbrev, abbr, short
		 *
		 * @return string
		 */
		public static function wp_locale_month( $month, $format = 'month' ) {
			$month = trim( $month );

			$valid_formats = [
				'full',
				'month',
				'abbreviation',
				'abbrev',
				'abbr',
				'short',
			];

			// if there isn't a valid format, bail without providing a localized string
			if ( ! in_array( $format, $valid_formats ) ) {
				return $month;
			}

			if ( empty( self::$localized_months ) ) {
				self::build_localized_months();
			}

			// make sure numeric months are valid
			if ( is_numeric( $month ) ) {
				$month_num = (int) $month;

				// if the month num falls out of range, bail without localizing
				if ( 0 > $month_num || 12 < $month_num ) {
					return $month;
				}
			} else {
				$months = [
					'Jan',
					'Feb',
					'Mar',
					'Apr',
					'May',
					'Jun',
					'Jul',
					'Aug',
					'Sep',
					'Oct',
					'Nov',
					'Dec',
				];

				// convert the provided month to a 3-character month and find it in the months array so we
				// can build an appropriate month number
				$month_num = array_search( ucwords( substr( $month, 0, 3 ) ), $months );

				// if we can't find the provided month in our month list, bail without localizing
				if ( false === $month_num ) {
					return $month;
				}

				// let's increment the num because months start at 01 rather than 00
				$month_num++;
			}

			$month_num = str_pad( $month_num, 2, '0', STR_PAD_LEFT );

			$type = ( 'full' === $format || 'month' === $format ) ? 'full' : 'short';

			return self::$localized_months[ $type ][ $month_num ];
		}

		// DEPRECATED METHODS
		// @codingStandardsIgnoreStart
		/**
		 * Deprecated camelCase version of self::date_only
		 *
		 * @param int|string $date        The date (timestamp or string).
		 * @param bool       $isTimestamp Is $date in timestamp format?
		 *
		 * @return string The date only in DB format.
		 */
		public static function dateOnly( $date, $isTimestamp = false ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::date_only' );
			return self::date_only( $date, $isTimestamp );
		}

		/**
		 * Deprecated camelCase version of self::time_only
		 *
		 * @param string $date The date.
		 *
		 * @return string The time only in DB format.
		 */
		public static function timeOnly( $date ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::time_only' );
			return self::time_only( $date );
		}

		/**
		 * Deprecated camelCase version of self::hour_only
		 *
		 * @param string $date The date.
		 *
		 * @return string The hour only.
		 */
		public static function hourOnly( $date ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::hour_only' );
			return self::hour_only( $date );
		}

		/**
		 * Deprecated camelCase version of self::minutes_only
		 *
		 * @param string $date The date.
		 *
		 * @return string The minute only.
		 */
		public static function minutesOnly( $date ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::minutes_only' );
			return self::minutes_only( $date );
		}

		/**
		 * Deprecated camelCase version of self::meridian_only
		 *
		 * @param string $date The date.
		 *
		 * @return string The meridian only in DB format.
		 */
		public static function meridianOnly( $date ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::meridian_only' );
			return self::meridian_only( $date );
		}

		/**
		 * Returns the end of a given day.
		 *
		 * @deprecated since 3.10 - use tribe_event_end_of_day()
		 * @todo       remove in 4.1
		 *
		 * @param int|string $date        The date (timestamp or string).
		 * @param bool       $isTimestamp Is $date in timestamp format?
		 *
		 * @return string The date and time of the end of a given day
		 */
		public static function endOfDay( $date, $isTimestamp = false ) {
			_deprecated_function( __METHOD__, '3.10', 'tribe_event_end_of_day' );

			if ( $isTimestamp ) {
				$date = date( self::DBDATEFORMAT, $date );
			}

			return tribe_event_end_of_day( $date, self::DBDATETIMEFORMAT );
		}

		/**
		 * Returns the beginning of a given day.
		 *
		 * @deprecated since 3.10
		 * @todo       remove in 4.1
		 *
		 * @param int|string $date        The date (timestamp or string).
		 * @param bool       $isTimestamp Is $date in timestamp format?
		 *
		 * @return string The date and time of the beginning of a given day.
		 */
		public static function beginningOfDay( $date, $isTimestamp = false ) {
			_deprecated_function( __METHOD__, '3.10', 'tribe_event_beginning_of_day' );

			if ( $isTimestamp ) {
				$date = date( self::DBDATEFORMAT, $date );
			}

			return tribe_event_beginning_of_day( $date, self::DBDATETIMEFORMAT );
		}

		/**
		 * Deprecated camelCase version of self::time_between
		 *
		 * @param string $date1 The first date.
		 * @param string $date2 The second date.
		 *
		 * @return int The number of seconds between the dates.
		 */
		public static function timeBetween( $date1, $date2 ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::time_between' );
			return self::time_between( $date1, $date2 );
		}

		/**
		 * Deprecated camelCase version of self::date_diff
		 *
		 * @param string $date1 The first date.
		 * @param string $date2 The second date.
		 *
		 * @return int The number of days between two dates.
		 */
		public static function dateDiff( $date1, $date2 ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::date_diff' );
			return self::date_diff( $date1, $date2 );
		}

		/**
		 * Deprecated camelCase version of self::get_last_day_of_month
		 *
		 * @param int $timestamp THe timestamp.
		 *
		 * @return string The last day of the month.
		 */
		public static function getLastDayOfMonth( $timestamp ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::get_last_day_of_month' );
			return self::get_last_day_of_month( $timestamp );
		}

		/**
		 * Deprecated camelCase version of self::is_weekday
		 *
		 * @param int $curDate A timestamp.
		 *
		 * @return bool If the timestamp is a weekday.
		 */
		public static function isWeekday( $curdate ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_weekday' );
			return self::is_weekday( $curdate );
		}

		/**
		 * Deprecated camelCase version of self::is_weekend
		 *
		 * @param int $curDate A timestamp.
		 *
		 * @return bool If the timestamp is a weekend.
		 */
		public static function isWeekend( $curdate ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_weekend' );
			return self::is_weekend( $curdate );
		}

		/**
		 * Deprecated camelCase version of self::get_last_day_of_week_in_month
		 *
		 * @param int $curdate     A timestamp.
		 * @param int $day_of_week The index of the day of the week.
		 *
		 * @return int The timestamp of the date that fits the qualifications.
		 */
		public static function getLastDayOfWeekInMonth( $curdate, $day_of_week ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::get_last_day_of_week_in_month' );
			return self::get_last_day_of_week_in_month( $curdate, $day_of_week );
		}

		/**
		 * Deprecated camelCase version of self::get_first_day_of_week_in_month
		 *
		 * @param int $curdate     A timestamp.
		 * @param int $day_of_week The index of the day of the week.
		 *
		 * @return int The timestamp of the date that fits the qualifications.
		 */
		public static function getFirstDayOfWeekInMonth( $curdate, $day_of_week ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::get_fist_day_of_week_in_month' );
			return self::get_first_day_of_week_in_month( $curdate, $day_of_week );
		}

		/**
		 * Deprecated camelCase version of self::number_to_ordinal
		 *
		 * @param int $number A number.
		 *
		 * @return string The ordinal for that number.
		 */
		public static function numberToOrdinal( $number ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::number_to_ordinal' );
			return self::number_to_ordinal( $number );
		}

		/**
		 * Deprecated camelCase version of self::is_timestamp
		 *
		 * @param $timestamp
		 *
		 * @return bool
		 */
		public static function isTimestamp( $timestamp ) {
			_deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_timestamp' );
			return self::is_timestamp( $timestamp );
		}

		/**
		 * Gets the timestamp of a day in week, month and year context.
		 *
		 * Kudos to [icedwater StackOverflow user](http://stackoverflow.com/users/1091386/icedwater) in
		 * [his answer](http://stackoverflow.com/questions/924246/get-the-first-or-last-friday-in-a-month).
		 *
		 * Usage examples:
		 * "The second Wednesday of March 2015" - `get_day_timestamp( 3, 2, 3, 2015, 1)`
		 * "The last Friday of December 2015" - `get_day_timestamp( 5, 1, 12, 2015, -1)`
		 * "The first Monday of April 2016 - `get_day_timestamp( 1, 1, 4, 2016, 1)`
		 * "The penultimate Thursday of January 2012" - `get_day_timestamp( 4, 2, 1, 2012, -1)`
		 *
		 * @param int $day_of_week    The day representing the number in the week, Monday is `1`, Tuesday is `2`, Sunday is `7`
		 * @param int $week_in_month  The week number in the month; first week is `1`, second week is `2`; when direction is reverse
		 *                  then `1` is last week of the month, `2` is penultimate week of the month and so on.
		 * @param int $month          The month number in the year, January is `1`
		 * @param int $year           The year number, e.g. "2015"
		 * @param int $week_direction Either `1` or `-1`; the direction for the search referring to the week, defaults to `1`
		 *                       to specify weeks in natural order so:
		 *                       $week_direction `1` and $week_in_month `1` means "first week of the month"
		 *                       $week_direction `1` and $week_in_month `3` means "third week of the month"
		 *                       $week_direction `-1` and $week_in_month `1` means "last week of the month"
		 *                       $week_direction `-1` and $week_in_month `2` means "penultimmate week of the month"
		 *
		 * @return int The day timestamp
		 */
		public static function get_weekday_timestamp( $day_of_week, $week_in_month, $month, $year, $week_direction = 1 ) {
			if (
				! (
					is_numeric( $day_of_week )
					&& is_numeric( $week_in_month )
					&& is_numeric( $month )
					&& is_numeric( $year )
					&& is_numeric( $week_direction )
					&& in_array( $week_direction, [ -1, 1 ] )
				)
			) {
				return false;
			}

			if ( $week_direction > 0 ) {
				$startday = 1;
			} else {
				$startday = date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
			}

			$start   = mktime( 0, 0, 0, $month, $startday, $year );
			$weekday = date( 'N', $start );

			if ( $week_direction * $day_of_week >= $week_direction * $weekday ) {
				$offset = - $week_direction * 7;
			} else {
				$offset = 0;
			}

			$offset += $week_direction * ( $week_in_month * 7 ) + ( $day_of_week - $weekday );

			return mktime( 0, 0, 0, $month, $startday + $offset, $year );
		}

		/**
		 * Unescapes date format strings to be used in functions like `date`.
		 *
		 * Double escaping happens when storing a date format in the database.
		 *
		 * @param mixed $date_format A date format string.
		 *
		 * @return mixed Either the original input or an unescaped date format string.
		 */
		public static function unescape_date_format( $date_format ) {
			if ( ! is_string( $date_format ) ) {
				return $date_format;
			}

			// Why so simple? Let's handle other cases as those come up. We have tests in place!
			return str_replace( '\\\\', '\\', $date_format );
		}

		/**
		 * Builds a date object from a given datetime and timezone.
		 *
		 * @since 4.9.5
		 *
		 * @param string|DateTime|int      $datetime      A `strtotime` parsable string, a DateTime object or
		 *                                                a timestamp; defaults to `now`.
		 * @param string|DateTimeZone|null $timezone      A timezone string, UTC offset or DateTimeZone object;
		 *                                                defaults to the site timezone; this parameter is ignored
		 *                                                if the `$datetime` parameter is a DatTime object.
		 * @param bool                     $with_fallback Whether to return a DateTime object even when the date data is
		 *                                                invalid or not; defaults to `true`.
		 *
		 * @return DateTime|Date_i18n|false A DateTime|Date_i18n object built using the specified date, time and timezone; if `$with_fallback`
		 *                        is set to `false` then `false` will be returned if a DateTime object could not be built.
		 */
		public static function build_date_object( $datetime = 'now', $timezone = null, $with_fallback = true ) {
			if ( $datetime instanceof DateTime ) {
				return clone $datetime;
			}

			if ( class_exists( 'DateTimeImmutable' ) && $datetime instanceof DateTimeImmutable ) {
				// Return the mutable version of the date.
				return Date_I18n::createFromImmutable( $datetime );
			}

			$timezone_object = null;
			$datetime = empty( $datetime ) ? 'now' : $datetime;

			try {
				// PHP 5.2 will not throw an exception but will generate an error.
				$utc = new DateTimeZone( 'UTC' );
				$timezone_object = Tribe__Timezones::build_timezone_object( $timezone );

				if ( self::is_timestamp( $datetime ) ) {
					$timestamp_timezone = $timezone ? $timezone_object : $utc;

					return new Date_I18n( '@' . $datetime, $timestamp_timezone );
				}

				set_error_handler( 'tribe_catch_and_throw' );
				$date = new Date_I18n( $datetime, $timezone_object );
				restore_error_handler();
			} catch ( Exception $e ) {
				// If we encounter an error, we need to restore after catching.
				restore_error_handler();

				if ( $timezone_object === null ) {
					$timezone_object = Tribe__Timezones::build_timezone_object( $timezone );
				}

				return $with_fallback
					? new Date_I18n( 'now', $timezone_object )
					: false;
			}

			return $date;
		}

		/**
		 * Validates a date string to make sure it can be used to build DateTime objects.
		 *
		 * @since 4.9.5
		 *
		 * @param string $date The date string that should validated.
		 *
		 * @return bool Whether the date string can be used to build DateTime objects, and is thus parsable by functions
		 *              like `strtotime`, or not.
		 */
		public static function is_valid_date( $date ) {
			static $cache_var_name = __FUNCTION__;

			$cache_date_check = tribe_get_var( $cache_var_name, [] );

			if ( isset( $cache_date_check[ $date ] ) ) {
				return $cache_date_check[ $date ];
			}

			$cache_date_check[ $date ] = self::build_date_object( $date, null, false ) instanceof DateTimeInterface;

			tribe_set_var( $cache_var_name, $cache_date_check );

			return $cache_date_check[ $date ];
		}

		/**
		 * Returns the DateTime object representing the start of the week for a date.
		 *
		 * @since 4.9.21
		 *
		 * @throws Exception
		 *
		 * @param string|int|\DateTime $date          The date string, timestamp or object.
		 * @param int|null             $start_of_week The number representing the start of week day as handled by
		 *                                            WordPress: `0` (for Sunday) through `6` (for Saturday).
		 *
		 * @return array An array of objects representing the week start and end days, or `false` if the
		 *                        supplied date is invalid. The timezone of the returned object is set to the site one.
		 *                        The week start has its time set to `00:00:00`, the week end will have its time set
		 *                        `23:59:59`.
		 */
		public static function get_week_start_end( $date, $start_of_week = null ) {
			static $cache_var_name = __FUNCTION__;

			$cache_week_start_end = tribe_get_var( $cache_var_name, [] );

			$date_obj = static::build_date_object( $date );
			$date_obj->setTime( 0, 0, 0 );

			$date_string = $date_obj->format( static::DBDATEFORMAT );

			// `0` (for Sunday) through `6` (for Saturday), the way WP handles the `start_of_week` option.
			$week_start_day = null !== $start_of_week
				? (int) $start_of_week
				: (int) get_option( 'start_of_week', 0 );

			$memory_cache_key = "{$date_string}:{$week_start_day}";

			if ( isset( $cache_week_start_end[ $memory_cache_key ] ) ) {
				return $cache_week_start_end[ $memory_cache_key ];
			}

			$cache_key = md5(
				__METHOD__ . serialize( [ $date_obj->format( static::DBDATEFORMAT ), $week_start_day ] )
			);
			$cache = tribe( 'cache' );

			if ( false !== $cached = $cache[ $cache_key ] ) {
				return $cached;
			}

			// `0` (for Sunday) through `6` (for Saturday), the way WP handles the `start_of_week` option.
			$date_day = (int) $date_obj->format( 'w' );

			$week_offset = 0;
			if ( 0 === $date_day && 0 !== $week_start_day ) {
				$week_offset = 0;
			} elseif ( $date_day < $week_start_day ) {
				// If the current date of the week is before the start of the week, move back a week.
				$week_offset = -1;
			} elseif ( 0 === $date_day ) {
				// When start of the week is on a sunday we add a week.
				$week_offset = 1;
			}

			$week_start = clone $date_obj;

			/*
			 * From the PHP docs, the `W` format stands for:
			 * - ISO-8601 week number of year, weeks starting on Monday
			 */
			$week_start->setISODate(
				(int) $week_start->format( 'o' ),
				(int) $week_start->format( 'W' ) + $week_offset,
				$week_start_day
			);

			$week_end = clone $week_start;
			// Add 6 days, then move at the end of the day.
			$week_end->add( new DateInterval( 'P6D' ) );
			$week_end->setTime( 23, 59, 59 );

			$week_start = static::immutable( $week_start );
			$week_end   = static::immutable( $week_end );

			$cache[ $cache_key ]                       = [ $week_start, $week_end ];
			$cache_week_start_end[ $memory_cache_key ] = [ $week_start, $week_end ];

			tribe_set_var( $cache_var_name, $cache_week_start_end );

			return [ $week_start, $week_end ];
		}

		/**
		 * Given a specific DateTime we determine the end of that day based on our Internal End of Day Cut-off.
		 *
		 * @since 4.11.2
		 *
		 * @param string|DateTimeInterface $date    Date that we are getting the end of day from.
		 * @param null|string              $cutoff  Which cutoff to use.
		 *
		 * @return DateTimeInterface|false Returns a DateTimeInterface when a valid date is given or false.
		 */
		public static function get_shifted_end_of_day( $date, $cutoff = null ) {
			$date_obj = static::build_date_object( $date );

			if ( ! $date_obj ) {
				return false;
			}

			$start_of_day = clone $date_obj;
			$end_of_day   = clone $date_obj;

			if ( empty( $cutoff ) || ! is_string( $cutoff ) || false === strpos( $cutoff, ':' ) ) {
				$cutoff = tribe_get_option( 'multiDayCutoff', '00:00' );
			}

			list( $hours_to_add, $minutes_to_add ) = array_map( 'absint', explode( ':', $cutoff ) );

			$seconds_to_add = ( $hours_to_add * HOUR_IN_SECONDS ) + ( $minutes_to_add * MINUTE_IN_SECONDS );
			if ( 0 !== $seconds_to_add ) {
				$interval = static::interval( "PT{$seconds_to_add}S" );
			}

			$start_of_day->setTime( '0', '0', '0' );
			$end_of_day->setTime( '23', '59', '59' );

			if ( 0 !== $seconds_to_add ) {
				$start_of_day->add( $interval );
				$end_of_day->add( $interval );
			}

			if ( $end_of_day >= $date_obj && $date_obj >= $start_of_day ) {
				return $end_of_day;
			}

			$start_of_day->sub( static::interval( 'P1D' ) );

			if ( $start_of_day < $date_obj ) {
				$end_of_day->sub( static::interval( 'P1D' ) );
			}

			return $end_of_day;
		}

		/**
		 * Given a specific DateTime we determine the start of that day based on our Internal End of Day Cut-off.
		 *
		 * @since 4.11.2
		 *
		 * @param string|DateTimeInterface $date    Date that we are getting the start of day from.
		 * @param null|string              $cutoff  Which cutoff to use.
		 *
		 * @return DateTimeInterface|false Returns a DateTimeInterface when a valid date is given or false.
		 */
		public static function get_shifted_start_of_day( $date, $cutoff = null ) {
			$date_obj = static::build_date_object( $date );

			if ( ! $date_obj ) {
				return false;
			}

			$start_of_day = clone $date_obj;
			$end_of_day   = clone $date_obj;

			if ( empty( $cutoff ) || ! is_string( $cutoff ) || false === strpos( $cutoff, ':' ) ) {
				$cutoff = tribe_get_option( 'multiDayCutoff', '00:00' );
			}

			list( $hours_to_add, $minutes_to_add ) = array_map( 'absint', explode( ':', $cutoff ) );

			$seconds_to_add = ( $hours_to_add * HOUR_IN_SECONDS ) + ( $minutes_to_add * MINUTE_IN_SECONDS );
			if ( 0 !== $seconds_to_add ) {
				$interval = static::interval( "PT{$seconds_to_add}S" );
			}

			$start_of_day->setTime( '0', '0', '0' );
			$end_of_day->setTime( '23', '59', '59' );

			if ( 0 !== $seconds_to_add ) {
				$start_of_day->add( $interval );
				$end_of_day->add( $interval );
			}

			if ( $end_of_day <= $date_obj && $date_obj >= $start_of_day ) {
				return $start_of_day;
			}

			$end_of_day->sub( static::interval( 'P1D' ) );

			if ( $end_of_day > $date_obj ) {
				$start_of_day->sub( static::interval( 'P1D' ) );
			}

			return $start_of_day;
		}

		/**
		 * Builds and returns a `DateInterval` object from the interval specification.
		 *
		 * For performance purposes the use of `DateInterval` specifications is preferred, so `P1D` is better than
		 * `1 day`.
		 *
		 * @since 4.10.2
		 *
		 * @return DateInterval The built date interval object.
		 */
		public static function interval( $interval_spec ) {
			try {
				$interval = new \DateInterval( $interval_spec );
			} catch ( \Exception $e ) {
				$interval = DateInterval::createFromDateString( $interval_spec );
			}

			return $interval;
		}

		/**
		 * Builds the immutable version of a date from a string, integer (timestamp) or \DateTime object.
		 *
		 * It's the immutable version of the `Tribe__Date_Utils::build_date_object` method.
		 *
		 * @since 4.10.2
		 *
		 * @param string|DateTime|int      $datetime      A `strtotime` parsable string, a DateTime object or
		 *                                                a timestamp; defaults to `now`.
		 * @param string|DateTimeZone|null $timezone      A timezone string, UTC offset or DateTimeZone object;
		 *                                                defaults to the site timezone; this parameter is ignored
		 *                                                if the `$datetime` parameter is a DatTime object.
		 * @param bool                     $with_fallback Whether to return a DateTime object even when the date data is
		 *                                                invalid or not; defaults to `true`.
		 *
		 * @return DateTimeImmutable|false A DateTime object built using the specified date, time and timezone; if
		 *                                 `$with_fallback` is set to `false` then `false` will be returned if a
		 *                                 DateTime object could not be built.
		 */
		static function immutable( $datetime = 'now', $timezone = null, $with_fallback = true ) {
			if ( $datetime instanceof DateTimeImmutable ) {
				return $datetime;
			}

			if ( $datetime instanceof DateTime ) {
				return Date_I18n_Immutable::createFromMutable( $datetime );
			}

			$mutable = static::build_date_object( $datetime, $timezone, $with_fallback );

			if ( false === $mutable ) {
				return false;
			}

			$cache_key = md5( ( __METHOD__ . $mutable->getTimezone()->getName() . $mutable->getTimestamp() ) );
			$cache     = tribe( 'cache' );

			if ( false !== $cached = $cache[ $cache_key ] ) {
				return $cached;
			}

			$immutable = Date_I18n_Immutable::createFromMutable( $mutable );

			$cache[ $cache_key ] = $immutable;

			return $immutable;
		}

		/**
		 * Builds a date object from a given datetime and timezone.
		 *
		 * An alias of the `Tribe__Date_Utils::build_date_object` function.
		 *
		 * @since 4.10.2
		 *
		 * @param string|DateTime|int      $datetime      A `strtotime` parsable string, a DateTime object or
		 *                                                a timestamp; defaults to `now`.
		 * @param string|DateTimeZone|null $timezone      A timezone string, UTC offset or DateTimeZone object;
		 *                                                defaults to the site timezone; this parameter is ignored
		 *                                                if the `$datetime` parameter is a DatTime object.
		 * @param bool                     $with_fallback Whether to return a DateTime object even when the date data is
		 *                                                invalid or not; defaults to `true`.
		 *
		 * @return DateTime|false A DateTime object built using the specified date, time and timezone; if `$with_fallback`
		 *                        is set to `false` then `false` will be returned if a DateTime object could not be built.
		 */
		public static function mutable( $datetime = 'now', $timezone = null, $with_fallback = true ) {
			return static::build_date_object( $datetime, $timezone, $with_fallback );
		}
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit