PluginProbe ʕ •ᴥ•ʔ
The Events Calendar / 4.6.14
The Events Calendar v4.6.14
6.16.3 6.16.2 6.16.0 6.16.1 5.1.1.1 5.1.1.2 5.1.2.1 5.1.2.2 5.1.3 5.1.3.1 5.1.4 5.1.4.1 5.1.5 5.1.5.1 5.1.6 5.1.6.1 5.10.0 5.10.1 5.11.0 5.12.0 5.12.1 5.12.2 5.12.3 5.12.4 5.13.0 5.14.0 5.14.0.1 5.14.0.2 5.14.0.3 5.14.0.4 5.14.1 5.14.2 5.14.2.1 5.15.0 5.15.0.1 5.16.0 5.16.1 5.16.1.1 5.16.2 5.16.2.1 5.16.3 5.16.3.1 5.16.4 5.16.4.1 5.2.0 5.2.0.1 5.2.1 5.2.1.1 5.2.1.2 5.3.0 5.3.0.1 5.3.1 5.3.1.1 5.3.1.2 5.3.2 5.3.2.1 5.3.2.2 5.4.0 5.4.0.1 5.4.0.2 5.4.0.3 trunk 5.5.0 1.5 5.5.0.1 1.5.1 5.5.0.2 1.5.2 5.6.0 1.5.3 5.7.0 1.5.4 5.7.1 1.5.5 5.8.0 1.5.6 5.8.1 1.6 5.8.2 1.6.1 5.9.0 1.6.2 5.9.1 1.6.3 5.9.2 1.6.4 6.0.0 1.6.5 6.0.0.1 2.0 6.0.1 2.0.1 6.0.1.1 2.0.10 6.0.10 2.0.11 6.0.11 2.0.2 6.0.12 2.0.3 6.0.13 2.0.4 6.0.13.1 2.0.5 6.0.2 2.0.6 6.0.3 2.0.7 6.0.3.1 2.0.8 6.0.4 2.0.9 6.0.5 3.0 6.0.6 3.0.1 6.0.6.1 3.0.2 6.0.6.2 3.0.3 6.0.7 3.1 6.0.7.1 3.10 6.0.8 3.10.1 6.0.9 3.11 6.1.0 3.11.1 6.1.0.1 3.11.2 6.1.0.2 3.12 6.1.1 3.12.1 6.1.2 3.12.2 6.1.2.1 3.12.3 6.1.2.2 3.12.4 6.1.3 3.12.5 6.1.4 3.12.6 6.10.0 3.2 6.10.1 3.3 6.10.1.1 3.3.1 6.10.2 3.4 6.10.3 3.4.1 6.11.0 3.5 6.11.0.1 3.5.1 6.11.1 3.6 6.11.2 3.6.1 6.11.2.1 3.7 6.12.0 3.8 6.12.0.1 3.8.1 6.13.0 3.9 6.13.1 3.9.1 6.13.2 3.9.2 6.13.2.1 3.9.3 6.14.0 4.0 6.14.1 4.0.1 6.14.2 4.0.2 6.15.0 4.0.3 6.15.0.1 4.0.4 6.15.1 4.0.5 6.15.1.1 4.0.6 6.15.10 4.0.7 6.15.11 4.1 6.15.12 4.1.0.1 6.15.12.1 4.1.1 6.15.12.2 4.1.1.1 6.15.13 4.1.2 6.15.13.1 4.1.3 6.15.14 4.1.4 6.15.15 4.2 6.15.16 4.2.1 6.15.16.1 4.2.1.1 6.15.17 4.2.2 6.15.17.1 4.2.3 6.15.18 4.2.4 6.15.19 4.2.5 6.15.2 4.2.6 6.15.20 4.2.7 6.15.3 4.3 6.15.4 4.3.0.2 6.15.5 4.3.1 6.15.6 4.3.1.2 6.15.7 4.3.2.1 6.15.8 4.3.3.1 6.15.9 4.3.4.1 6.2.0 4.3.4.3 6.2.0.1 4.3.5.1 6.2.1 4.4 6.2.2 4.4.0.2 6.2.2.1 4.4.1 6.2.3 4.4.1.2 6.2.3.1 4.4.2.1 6.2.3.2 4.4.3.1 6.2.4 4.4.4.1 6.2.5 4.4.5.1 6.2.6 4.5 6.2.6.1 4.5.0.1 6.2.7 4.5.0.3 6.2.8 4.5.1.1 6.2.8.1 4.5.10 6.2.8.2 4.5.10.2 6.2.9 4.5.11.1 6.3.0 4.5.12 6.3.1 4.5.12.1 6.3.2 4.5.12.2 6.3.3 4.5.12.4 6.3.3.1 4.5.13.1 6.3.4 4.5.2 6.3.5 4.5.2.2 6.3.6 4.5.3.1 6.3.7 4.5.4.1 6.4.0 4.5.5.1 6.4.0.1 4.5.6.1 6.5.0 4.5.7.1 6.5.0.1 4.5.8 6.5.1 4.5.8.2 6.5.1.1 4.5.9.1 6.5.1.2 4.6.0.1 6.5.1.3 4.6.1.1 6.5.1.4 4.6.10 6.5.1.5 4.6.10.2 6.5.1.6 4.6.11 6.5.2 4.6.11.2 6.6.0 4.6.12.1 6.6.0.1 4.6.13.1 6.6.0.2 4.6.14 6.6.1 4.6.14.2 6.6.2 4.6.15.1 6.6.3 4.6.16.1 6.6.4 4.6.17.1 6.6.4.1 4.6.18.1 6.6.4.2 4.6.19.1 6.7.0 4.6.2.1 6.7.1 4.6.20 6.8.0 4.6.20.2 6.8.1 4.6.21.1 6.8.2 4.6.22 6.8.2.1 4.6.22.2 6.8.3 4.6.23.1 6.9.0 4.6.24 6.9.1 4.6.24.2 4.6.25.1 4.6.26 4.6.26.2 4.6.3.1 4.6.4.1 4.6.5.1 4.6.6.1 4.6.7.1 4.6.8.1 4.6.9.1 4.7 4.7.0.2 4.7.1.1 4.7.2.1 4.7.3.1 4.7.4.1 4.8 4.8.0.2 4.8.1.1 4.8.2.1 4.9.0.1 4.9.0.2 4.9.0.4 4.9.1 4.9.1.2 4.9.10.1 4.9.11.1 4.9.12.1 4.9.13.1 4.9.14.1 4.9.2.1 4.9.3 4.9.3.1 4.9.3.3 4.9.4.1 4.9.5.1 4.9.6.1 4.9.7.1 4.9.8.1 4.9.9.1 5.0.0 5.0.0.1 5.0.0.3 5.0.1.1 5.0.1.2 5.0.2 5.0.2.2 5.0.2.3 5.0.3 5.0.3.2 5.0.3.3 5.1.0.1 5.1.0.2
the-events-calendar / common / src / Tribe / Date_Utils.php
the-events-calendar / common / src / Tribe Last commit date
Admin 8 years ago Ajax 8 years ago Asset 8 years ago Customizer 8 years ago Documentation 8 years ago Duplicate 8 years ago Image 8 years ago JSON_LD 8 years ago Languages 8 years ago Log 8 years ago Meta 8 years ago PUE 8 years ago Process 8 years ago REST 8 years ago Service_Providers 8 years ago Support 8 years ago Tabbed_View 8 years ago Utils 8 years ago Validator 8 years ago Abstract_Deactivation.php 8 years ago App_Shop.php 8 years ago Assets.php 8 years ago Assets_Pipeline.php 8 years ago Autoloader.php 8 years ago Cache.php 8 years ago Cache_Listener.php 8 years ago Changelog_Reader.php 8 years ago Container.php 8 years ago Context.php 8 years ago Cost_Utils.php 8 years ago Credits.php 8 years ago Customizer.php 8 years ago Data.php 8 years ago Date_Utils.php 8 years ago Debug.php 8 years ago Dependency.php 8 years ago Deprecation.php 8 years ago Error.php 8 years ago Exception.php 8 years ago Extension.php 8 years ago Extension_Loader.php 8 years ago Field.php 8 years ago Field_Conditional.php 8 years ago Log.php 8 years ago Main.php 8 years ago Notices.php 8 years ago Plugin_Meta_Links.php 8 years ago Plugins.php 8 years ago Plugins_API.php 8 years ago Post_History.php 8 years ago Post_Transient.php 8 years ago Rewrite.php 8 years ago Settings.php 8 years ago Settings_Manager.php 8 years ago Settings_Tab.php 8 years ago Simple_Table.php 8 years ago Support.php 8 years ago Tabbed_View.php 8 years ago Template.php 8 years ago Template_Factory.php 8 years ago Template_Part_Cache.php 8 years ago Templates.php 8 years ago Terms.php 8 years ago Timezones.php 8 years ago Tracker.php 8 years ago Validate.php 8 years ago View_Helpers.php 8 years ago
Date_Utils.php
1173 lines
1 <?php
2 /**
3 * Date utility functions used throughout TEC + Addons
4 */
5
6 // Don't load directly
7 if ( ! defined( 'ABSPATH' ) ) {
8 die( '-1' );
9 }
10
11 if ( ! class_exists( 'Tribe__Date_Utils' ) ) {
12 class Tribe__Date_Utils {
13 // Default formats, they are overridden by WP options or by arguments to date methods
14 const DATEONLYFORMAT = 'F j, Y';
15 const TIMEFORMAT = 'g:i A';
16 const HOURFORMAT = 'g';
17 const MINUTEFORMAT = 'i';
18 const MERIDIANFORMAT = 'A';
19 const DBDATEFORMAT = 'Y-m-d';
20 const DBDATETIMEFORMAT = 'Y-m-d H:i:s';
21 const DBTIMEFORMAT = 'H:i:s';
22 const DBYEARMONTHTIMEFORMAT = 'Y-m';
23
24 private static $localized_months_full = array();
25 private static $localized_months_short = array();
26 private static $localized_weekdays = array();
27 private static $localized_months = array();
28
29 /**
30 * Try to format a Date to the Default Datepicker format
31 *
32 * @since 4.5.12
33 *
34 * @param string $date Original Date that came from a datepicker
35 * @param string|int $datepicker Datepicker format
36 * @return string
37 */
38 public static function maybe_format_from_datepicker( $date, $datepicker = null ) {
39 if ( ! is_numeric( $datepicker ) ) {
40 $datepicker = tribe_get_option( 'datepickerFormat' );
41 }
42
43 if ( is_numeric( $datepicker ) ) {
44 $datepicker = self::datepicker_formats( $datepicker );
45 }
46
47 $default_datepicker = self::datepicker_formats( 0 );
48
49 // If the current datepicker is the default we don't care
50 if ( $datepicker === $default_datepicker ) {
51 return $date;
52 }
53
54 return self::datetime_from_format( $datepicker, $date );
55 }
56
57 /**
58 * Get the datepicker format, that is used to translate the option from the DB to a string
59 *
60 * @param int $translate The db Option from datepickerFormat
61 * @return string|array If $translate is not set returns the full array, if not returns the `Y-m-d`
62 */
63 public static function datepicker_formats( $translate = null ) {
64
65 // The datepicker has issues when a period separator and no leading zero is used. Those formats are purposefully omitted.
66 $formats = array(
67 'Y-m-d',
68 'n/j/Y',
69 'm/d/Y',
70 'j/n/Y',
71 'd/m/Y',
72 'n-j-Y',
73 'm-d-Y',
74 'j-n-Y',
75 'd-m-Y',
76 'Y.m.d',
77 'm.d.Y',
78 'd.m.Y',
79 );
80
81 if ( is_null( $translate ) ) {
82 return $formats;
83 }
84
85 return isset( $formats[ $translate ] ) ? $formats[ $translate ] : $formats[0];
86 }
87
88 /**
89 * As PHP 5.2 doesn't have a good version of `date_parse_from_format`, this is how we deal with
90 * possible weird datepicker formats not working
91 *
92 * @param string $format The weird format you are using
93 * @param string $date The date string to parse
94 *
95 * @return string A DB formated Date, includes time if possible
96 */
97 public static function datetime_from_format( $format, $date ) {
98 // Reverse engineer the relevant date formats
99 $keys = array(
100 // Year with 4 Digits
101 'Y' => array( 'year', '\d{4}' ),
102
103 // Year with 2 Digits
104 'y' => array( 'year', '\d{2}' ),
105
106 // Month with leading 0
107 'm' => array( 'month', '\d{2}' ),
108
109 // Month without the leading 0
110 'n' => array( 'month', '\d{1,2}' ),
111
112 // Month ABBR 3 letters
113 'M' => array( 'month', '[A-Z][a-z]{2}' ),
114
115 // Month Name
116 'F' => array( 'month', '[A-Z][a-z]{2,8}' ),
117
118 // Day with leading 0
119 'd' => array( 'day', '\d{2}' ),
120
121 // Day without leading 0
122 'j' => array( 'day', '\d{1,2}' ),
123
124 // Day ABBR 3 Letters
125 'D' => array( 'day', '[A-Z][a-z]{2}' ),
126
127 // Day Name
128 'l' => array( 'day', '[A-Z][a-z]{5,8}' ),
129
130 // Hour 12h formatted, with leading 0
131 'h' => array( 'hour', '\d{2}' ),
132
133 // Hour 24h formatted, with leading 0
134 'H' => array( 'hour', '\d{2}' ),
135
136 // Hour 12h formatted, without leading 0
137 'g' => array( 'hour', '\d{1,2}' ),
138
139 // Hour 24h formatted, without leading 0
140 'G' => array( 'hour', '\d{1,2}' ),
141
142 // Minutes with leading 0
143 'i' => array( 'minute', '\d{2}' ),
144
145 // Seconds with leading 0
146 's' => array( 'second', '\d{2}' ),
147 );
148
149 $date_regex = "/{$keys['Y'][1]}-{$keys['m'][1]}-{$keys['d'][1]}( {$keys['H'][1]}:{$keys['i'][1]}:{$keys['s'][1]})?$/";
150
151 // if the date is already in Y-m-d or Y-m-d H:i:s, just return it
152 if ( preg_match( $date_regex, $date ) ) {
153 return $date;
154 }
155
156
157 // Convert format string to regex
158 $regex = '';
159 $chars = str_split( $format );
160 foreach ( $chars as $n => $char ) {
161 $last_char = isset( $chars[ $n - 1 ] ) ? $chars[ $n - 1 ] : '';
162 $skip_current = '\\' == $last_char;
163 if ( ! $skip_current && isset( $keys[ $char ] ) ) {
164 $regex .= '(?P<' . $keys[ $char ][0] . '>' . $keys[ $char ][1] . ')';
165 } elseif ( '\\' == $char ) {
166 $regex .= $char;
167 } else {
168 $regex .= preg_quote( $char );
169 }
170 }
171
172 $dt = array();
173
174 // Now try to match it
175 if ( preg_match( '#^' . $regex . '$#', $date, $dt ) ) {
176 // Remove unwanted Indexes
177 foreach ( $dt as $k => $v ) {
178 if ( is_int( $k ) ) {
179 unset( $dt[ $k ] );
180 }
181 }
182
183 // We need at least Month + Day + Year to work with
184 if ( ! checkdate( $dt['month'], $dt['day'], $dt['year'] ) ) {
185 return false;
186 }
187 } else {
188 return false;
189 }
190
191 $dt['month'] = str_pad( $dt['month'], 2, '0', STR_PAD_LEFT );
192 $dt['day'] = str_pad( $dt['day'], 2, '0', STR_PAD_LEFT );
193
194 $formatted = '{year}-{month}-{day}' . ( isset( $dt['hour'], $dt['minute'], $dt['second'] ) ? ' {hour}:{minute}:{second}' : '' );
195 foreach ( $dt as $key => $value ) {
196 $formatted = str_replace( '{' . $key . '}', $value, $formatted );
197 }
198
199 return $formatted;
200 }
201
202 /**
203 * Returns the date only.
204 *
205 * @param int|string $date The date (timestamp or string).
206 * @param bool $isTimestamp Is $date in timestamp format?
207 * @param string|null $format The format used
208 *
209 * @return string The date only in DB format.
210 */
211 public static function date_only( $date, $isTimestamp = false, $format = null ) {
212 $date = $isTimestamp ? $date : strtotime( $date );
213
214 if ( is_null( $format ) ) {
215 $format = self::DBDATEFORMAT;
216 }
217
218 return date( $format, $date );
219 }
220
221 /**
222 * Returns the time only.
223 *
224 * @param string $date The date.
225 *
226 * @return string The time only in DB format.
227 */
228 public static function time_only( $date ) {
229 $date = is_numeric( $date ) ? $date : strtotime( $date );
230 return date( self::DBTIMEFORMAT, $date );
231 }
232
233 /**
234 * Returns the hour only.
235 *
236 * @param string $date The date.
237 *
238 * @return string The hour only.
239 */
240 public static function hour_only( $date ) {
241 $date = is_numeric( $date ) ? $date : strtotime( $date );
242 return date( self::HOURFORMAT, $date );
243 }
244
245 /**
246 * Returns the minute only.
247 *
248 * @param string $date The date.
249 *
250 * @return string The minute only.
251 */
252 public static function minutes_only( $date ) {
253 $date = is_numeric( $date ) ? $date : strtotime( $date );
254 return date( self::MINUTEFORMAT, $date );
255 }
256
257 /**
258 * Returns the meridian (am or pm) only.
259 *
260 * @param string $date The date.
261 *
262 * @return string The meridian only in DB format.
263 */
264 public static function meridian_only( $date ) {
265 $date = is_numeric( $date ) ? $date : strtotime( $date );
266 return date( self::MERIDIANFORMAT, $date );
267 }
268
269 /**
270 * Returns the number of seconds (absolute value) between two dates/times.
271 *
272 * @param string $date1 The first date.
273 * @param string $date2 The second date.
274 *
275 * @return int The number of seconds between the dates.
276 */
277 public static function time_between( $date1, $date2 ) {
278 return abs( strtotime( $date1 ) - strtotime( $date2 ) );
279 }
280
281 /**
282 * The number of days between two arbitrary dates.
283 *
284 * @param string $date1 The first date.
285 * @param string $date2 The second date.
286 *
287 * @return int The number of days between two dates.
288 */
289 public static function date_diff( $date1, $date2 ) {
290 // Get number of days between by finding seconds between and dividing by # of seconds in a day
291 $days = self::time_between( $date1, $date2 ) / ( 60 * 60 * 24 );
292
293 return $days;
294 }
295
296 /**
297 * Returns the last day of the month given a php date.
298 *
299 * @param int $timestamp THe timestamp.
300 *
301 * @return string The last day of the month.
302 */
303 public static function get_last_day_of_month( $timestamp ) {
304 $curmonth = date( 'n', $timestamp );
305 $curYear = date( 'Y', $timestamp );
306 $nextmonth = mktime( 0, 0, 0, $curmonth + 1, 1, $curYear );
307 $lastDay = strtotime( date( self::DBDATETIMEFORMAT, $nextmonth ) . ' - 1 day' );
308
309 return date( 'j', $lastDay );
310 }
311
312 /**
313 * Returns true if the timestamp is a weekday.
314 *
315 * @param int $curDate A timestamp.
316 *
317 * @return bool If the timestamp is a weekday.
318 */
319 public static function is_weekday( $curdate ) {
320 return in_array( date( 'N', $curdate ), array( 1, 2, 3, 4, 5 ) );
321 }
322
323 /**
324 * Returns true if the timestamp is a weekend.
325 *
326 * @param int $curDate A timestamp.
327 *
328 * @return bool If the timestamp is a weekend.
329 */
330 public static function is_weekend( $curdate ) {
331 return in_array( date( 'N', $curdate ), array( 6, 7 ) );
332 }
333
334 /**
335 * 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.
336 *
337 * @param int $curdate A timestamp.
338 * @param int $day_of_week The index of the day of the week.
339 *
340 * @return int The timestamp of the date that fits the qualifications.
341 */
342 public static function get_last_day_of_week_in_month( $curdate, $day_of_week ) {
343 $nextdate = mktime( date( 'H', $curdate ), date( 'i', $curdate ), date( 's', $curdate ), date( 'n', $curdate ), self::get_last_day_of_month( $curdate ), date( 'Y', $curdate ) );;
344
345 while ( date( 'N', $nextdate ) != $day_of_week && $day_of_week != - 1 ) {
346 $nextdate = strtotime( date( self::DBDATETIMEFORMAT, $nextdate ) . ' - 1 day' );
347 }
348
349 return $nextdate;
350 }
351
352 /**
353 * Gets the first day of the week in a month (ie the first Tuesday).
354 *
355 * @param int $curdate A timestamp.
356 * @param int $day_of_week The index of the day of the week.
357 *
358 * @return int The timestamp of the date that fits the qualifications.
359 */
360 public static function get_first_day_of_week_in_month( $curdate, $day_of_week ) {
361 $nextdate = mktime( 0, 0, 0, date( 'n', $curdate ), 1, date( 'Y', $curdate ) );
362
363 while ( ! ( $day_of_week > 0 && date( 'N', $nextdate ) == $day_of_week ) &&
364 ! ( $day_of_week == - 1 && self::is_weekday( $nextdate ) ) &&
365 ! ( $day_of_week == - 2 && self::is_weekend( $nextdate ) ) ) {
366 $nextdate = strtotime( date( self::DBDATETIMEFORMAT, $nextdate ) . ' + 1 day' );
367 }
368
369 return $nextdate;
370 }
371
372 /**
373 * From http://php.net/manual/en/function.date.php
374 *
375 * @param int $number A number.
376 *
377 * @return string The ordinal for that number.
378 */
379 public static function number_to_ordinal( $number ) {
380 $output = $number . ( ( ( strlen( $number ) > 1 ) && ( substr( $number, - 2, 1 ) == '1' ) ) ?
381 'th' : date( 'S', mktime( 0, 0, 0, 0, substr( $number, - 1 ), 0 ) ) );
382
383 return apply_filters( 'tribe_events_number_to_ordinal', $output, $number );
384 }
385
386 /**
387 * check if a given string is a timestamp
388 *
389 * @param $timestamp
390 *
391 * @return bool
392 */
393 public static function is_timestamp( $timestamp ) {
394 if ( is_numeric( $timestamp ) && (int) $timestamp == $timestamp && date( 'U', $timestamp ) == $timestamp ) {
395 return true;
396 }
397
398 return false;
399 }
400
401 /**
402 * Accepts a string representing a date/time and attempts to convert it to
403 * the specified format, returning an empty string if this is not possible.
404 *
405 * @param $dt_string
406 * @param $new_format
407 *
408 * @return string
409 */
410 public static function reformat( $dt_string, $new_format ) {
411 $timestamp = self::is_timestamp( $dt_string ) ? $dt_string : strtotime( $dt_string );
412 $revised = date( $new_format, $timestamp );
413
414 return $revised ? $revised : '';
415 }
416
417 /**
418 * Accepts a numeric offset (such as "4" or "-6" as stored in the gmt_offset
419 * option) and converts it to a strtotime() style modifier that can be used
420 * to adjust a DateTime object, etc.
421 *
422 * @param $offset
423 *
424 * @return string
425 */
426 public static function get_modifier_from_offset( $offset ) {
427 $modifier = '';
428 $offset = (float) $offset;
429
430 // Separate out hours, minutes, polarity
431 $hours = (int) $offset;
432 $minutes = (int) ( ( $offset - $hours ) * 60 );
433 $polarity = ( $offset >= 0 ) ? '+' : '-';
434
435 // Correct hours and minutes to positive values
436 if ( $hours < 0 ) $hours *= -1;
437 if ( $minutes < 0 ) $minutes *= -1;
438
439 // Form the modifier string
440 if ( $hours >= 0 ) $modifier = "$polarity $hours hours ";
441 if ( $minutes > 0 ) $modifier .= "$minutes minutes";
442
443 return $modifier;
444 }
445
446 /**
447 * Returns the weekday of the 1st day of the month in
448 * "w" format (ie, Sunday is 0 and Saturday is 6) or
449 * false if this cannot be established.
450 *
451 * @param mixed $month
452 * @return int|bool
453 */
454 public static function first_day_in_month( $month ) {
455 try {
456 $date = new DateTime( $month );
457 $day_1 = new DateTime( $date->format( 'Y-m-01 ' ) );
458 return $day_1->format( 'w' );
459 }
460 catch ( Exception $e ) {
461 return false;
462 }
463 }
464
465 /**
466 * Returns the weekday of the last day of the month in
467 * "w" format (ie, Sunday is 0 and Saturday is 6) or
468 * false if this cannot be established.
469 *
470 * @param mixed $month
471 * @return int|bool
472 */
473 public static function last_day_in_month( $month ) {
474 try {
475 $date = new DateTime( $month );
476 $day_1 = new DateTime( $date->format( 'Y-m-t' ) );
477 return $day_1->format( 'w' );
478 }
479 catch ( Exception $e ) {
480 return false;
481 }
482 }
483
484 /**
485 * Returns the day of the week the week ends on, expressed as a "w" value
486 * (ie, Sunday is 0 and Saturday is 6).
487 *
488 * @param int $week_starts_on
489 *
490 * @return int
491 */
492 public static function week_ends_on( $week_starts_on ) {
493 if ( --$week_starts_on < 0 ) $week_starts_on = 6;
494 return $week_starts_on;
495 }
496
497 /**
498 * Helper method to convert EventAllDay values to a boolean
499 *
500 * @param mixed $all_day_value Value to check for "all day" status. All day values: (true, 'true', 'TRUE', 'yes')
501 *
502 * @return boolean Is value considered "All Day"?
503 */
504 public static function is_all_day( $all_day_value ) {
505 $all_day_value = trim( $all_day_value );
506
507 return (
508 'true' === strtolower( $all_day_value )
509 || 'yes' === strtolower( $all_day_value )
510 || true === $all_day_value
511 || 1 == $all_day_value
512 );
513 }
514
515 /**
516 * Given 2 datetime ranges, return whether the 2nd one occurs during the 1st one
517 * Note: all params should be unix timestamps
518 *
519 * @param integer $range_1_start timestamp for start of the first range
520 * @param integer $range_1_end timestamp for end of the first range
521 * @param integer $range_2_start timestamp for start of the second range
522 * @param integer $range_2_end timestamp for end of the second range
523 *
524 * @return bool
525 */
526 public static function range_coincides( $range_1_start, $range_1_end, $range_2_start, $range_2_end ) {
527
528 // Initialize the return value
529 $range_coincides = false;
530
531 /**
532 * conditions:
533 * range 2 starts during range 1 (range 2 start time is between start and end of range 1 )
534 * range 2 ends during range 1 (range 2 end time is between start and end of range 1 )
535 * range 2 encloses range 1 (range 2 starts before range 1 and ends after range 1)
536 */
537
538 $range_2_starts_during_range_1 = $range_2_start >= $range_1_start && $range_2_start < $range_1_end;
539 $range_2_ends_during_range_1 = $range_2_end > $range_1_start && $range_2_end <= $range_1_end;
540 $range_2_encloses_range_1 = $range_2_start < $range_1_start && $range_2_end > $range_1_end;
541
542 if ( $range_2_starts_during_range_1 || $range_2_ends_during_range_1 || $range_2_encloses_range_1 ) {
543 $range_coincides = true;
544 }
545
546 return $range_coincides;
547
548 }
549
550 /**
551 * Converts a locally-formatted date to a unix timestamp. This is a drop-in
552 * replacement for `strtotime()`, except that where strtotime assumes GMT, this
553 * assumes local time (as described below). If a timezone is specified, this
554 * function defers to strtotime().
555 *
556 * If there is a timezone_string available, the date is assumed to be in that
557 * timezone, otherwise it simply subtracts the value of the 'gmt_offset'
558 * option.
559 *
560 * @see strtotime()
561 * @uses get_option() to retrieve the value of 'gmt_offset'
562 *
563 * @param string $string A date/time string. See `strtotime` for valid formats
564 *
565 * @return int UNIX timestamp.
566 */
567 public static function wp_strtotime( $string ) {
568 // If there's a timezone specified, we shouldn't convert it
569 try {
570 $test_date = new DateTime( $string );
571 if ( 'UTC' != $test_date->getTimezone()->getName() ) {
572 return strtotime( $string );
573 }
574 } catch ( Exception $e ) {
575 return strtotime( $string );
576 }
577
578 $tz = get_option( 'timezone_string' );
579 if ( ! empty( $tz ) ) {
580 $date = date_create( $string, new DateTimeZone( $tz ) );
581 if ( ! $date ) {
582 return strtotime( $string );
583 }
584 $date->setTimezone( new DateTimeZone( 'UTC' ) );
585 return $date->format( 'U' );
586 } else {
587 $offset = (float) get_option( 'gmt_offset' );
588 $seconds = intval( $offset * HOUR_IN_SECONDS );
589 $timestamp = strtotime( $string ) - $seconds;
590 return $timestamp;
591 }
592 }
593
594 /**
595 * Returns an array of localized full month names.
596 *
597 * @return array
598 */
599 public static function get_localized_months_full() {
600 global $wp_locale;
601
602 if ( empty( self::$localized_months ) ) {
603 self::build_localized_months();
604 }
605
606 if ( empty( self::$localized_months_full ) ) {
607 self::$localized_months_full = array(
608 'January' => self::$localized_months['full']['01'],
609 'February' => self::$localized_months['full']['02'],
610 'March' => self::$localized_months['full']['03'],
611 'April' => self::$localized_months['full']['04'],
612 'May' => self::$localized_months['full']['05'],
613 'June' => self::$localized_months['full']['06'],
614 'July' => self::$localized_months['full']['07'],
615 'August' => self::$localized_months['full']['08'],
616 'September' => self::$localized_months['full']['09'],
617 'October' => self::$localized_months['full']['10'],
618 'November' => self::$localized_months['full']['11'],
619 'December' => self::$localized_months['full']['12'],
620 );
621 }
622
623 return self::$localized_months_full;
624 }
625
626 /**
627 * Returns an array of localized short month names.
628 *
629 * @return array
630 */
631 public static function get_localized_months_short() {
632 global $wp_locale;
633
634 if ( empty( self::$localized_months ) ) {
635 self::build_localized_months();
636 }
637
638 if ( empty( self::$localized_months_short ) ) {
639 self::$localized_months_short = array(
640 'Jan' => self::$localized_months['short']['01'],
641 'Feb' => self::$localized_months['short']['02'],
642 'Mar' => self::$localized_months['short']['03'],
643 'Apr' => self::$localized_months['short']['04'],
644 'May' => self::$localized_months['short']['05'],
645 'Jun' => self::$localized_months['short']['06'],
646 'Jul' => self::$localized_months['short']['07'],
647 'Aug' => self::$localized_months['short']['08'],
648 'Sep' => self::$localized_months['short']['09'],
649 'Oct' => self::$localized_months['short']['10'],
650 'Nov' => self::$localized_months['short']['11'],
651 'Dec' => self::$localized_months['short']['12'],
652 );
653 }
654
655 return self::$localized_months_short;
656 }
657
658 /**
659 * Returns an array of localized full week day names.
660 *
661 * @return array
662 */
663 public static function get_localized_weekdays_full() {
664 if ( empty( self::$localized_weekdays ) ) {
665 self::build_localized_weekdays();
666 }
667
668 return self::$localized_weekdays['full'];
669 }
670
671 /**
672 * Returns an array of localized short week day names.
673 *
674 * @return array
675 */
676 public static function get_localized_weekdays_short() {
677 if ( empty( self::$localized_weekdays ) ) {
678 self::build_localized_weekdays();
679 }
680
681 return self::$localized_weekdays['short'];
682 }
683
684 /**
685 * Returns an array of localized week day initials.
686 *
687 * @return array
688 */
689 public static function get_localized_weekdays_initial() {
690 if ( empty( self::$localized_weekdays ) ) {
691 self::build_localized_weekdays();
692 }
693
694 return self::$localized_weekdays['initial'];
695 }
696
697 /**
698 * Builds arrays of localized full, short and initialized weekdays.
699 */
700 private static function build_localized_weekdays() {
701 global $wp_locale;
702
703 for ( $i = 0; $i <= 6; $i++ ) {
704 $day = $wp_locale->get_weekday( $i );
705 self::$localized_weekdays['full'][ $i ] = $day;
706 self::$localized_weekdays['short'][ $i ] = $wp_locale->get_weekday_abbrev( $day );
707 self::$localized_weekdays['initial'][ $i ] = $wp_locale->get_weekday_initial( $day );
708 }
709 }
710
711 /**
712 * Builds arrays of localized full and short months.
713 *
714 * @since 4.4.3
715 */
716 private static function build_localized_months() {
717 global $wp_locale;
718
719 for ( $i = 1; $i <= 12; $i++ ) {
720 $month_number = str_pad( $i, 2, '0', STR_PAD_LEFT );
721 $month = $wp_locale->get_month( $month_number );
722 self::$localized_months['full'][ $month_number ] = $month;
723 self::$localized_months['short'][ $month_number ] = $wp_locale->get_month_abbrev( $month );
724 }
725 }
726
727 /**
728 * Return a WP Locale weekday in the specified format
729 *
730 * @since 4.4.3
731 *
732 * @param int|string $weekday Day of week
733 * @param string $format Weekday format: full, weekday, initial, abbreviation, abbrev, abbr, short
734 *
735 * @return string
736 */
737 public static function wp_locale_weekday( $weekday, $format = 'weekday' ) {
738 $weekday = trim( $weekday );
739
740 $valid_formats = array(
741 'full',
742 'weekday',
743 'initial',
744 'abbreviation',
745 'abbrev',
746 'abbr',
747 'short',
748 );
749
750 // if there isn't a valid format, bail without providing a localized string
751 if ( ! in_array( $format, $valid_formats ) ) {
752 return $weekday;
753 }
754
755 if ( empty( self::$localized_weekdays ) ) {
756 self::build_localized_weekdays();
757 }
758
759 // if the weekday isn't numeric, we need to convert to numeric in order to
760 // leverage self::localized_weekdays
761 if ( ! is_numeric( $weekday ) ) {
762 $days_of_week = array(
763 'Sun',
764 'Mon',
765 'Tue',
766 'Wed',
767 'Thu',
768 'Fri',
769 'Sat',
770 );
771
772 $day_index = array_search( ucwords( substr( $weekday, 0, 3 ) ), $days_of_week );
773
774 if ( false === $day_index ) {
775 return $weekday;
776 }
777
778 $weekday = $day_index;
779 }
780
781 switch ( $format ) {
782 case 'initial':
783 $type = 'initial';
784 break;
785 case 'abbreviation':
786 case 'abbrev':
787 case 'abbr':
788 case 'short':
789 $type = 'short';
790 break;
791 case 'weekday':
792 case 'full':
793 default:
794 $type = 'full';
795 break;
796 }
797
798 return self::$localized_weekdays[ $type ][ $weekday ];
799 }
800
801 /**
802 * Return a WP Locale month in the specified format
803 *
804 * @since 4.4.3
805 *
806 * @param int|string $month Month of year
807 * @param string $format Month format: full, month, abbreviation, abbrev, abbr, short
808 *
809 * @return string
810 */
811 public static function wp_locale_month( $month, $format = 'month' ) {
812 $month = trim( $month );
813
814 $valid_formats = array(
815 'full',
816 'month',
817 'abbreviation',
818 'abbrev',
819 'abbr',
820 'short',
821 );
822
823 // if there isn't a valid format, bail without providing a localized string
824 if ( ! in_array( $format, $valid_formats ) ) {
825 return $month;
826 }
827
828 if ( empty( self::$localized_months ) ) {
829 self::build_localized_months();
830 }
831
832 // make sure numeric months are valid
833 if ( is_numeric( $month ) ) {
834 $month_num = (int) $month;
835
836 // if the month num falls out of range, bail without localizing
837 if ( 0 > $month_num || 12 < $month_num ) {
838 return $month;
839 }
840 } else {
841 $months = array(
842 'Jan',
843 'Feb',
844 'Mar',
845 'Apr',
846 'May',
847 'Jun',
848 'Jul',
849 'Aug',
850 'Sep',
851 'Oct',
852 'Nov',
853 'Dec',
854 );
855
856 // convert the provided month to a 3-character month and find it in the months array so we
857 // can build an appropriate month number
858 $month_num = array_search( ucwords( substr( $month, 0, 3 ) ), $months );
859
860 // if we can't find the provided month in our month list, bail without localizing
861 if ( false === $month_num ) {
862 return $month;
863 }
864
865 // let's increment the num because months start at 01 rather than 00
866 $month_num++;
867 }
868
869 $month_num = str_pad( $month_num, 2, '0', STR_PAD_LEFT );
870
871 $type = ( 'full' === $format || 'month' === $format ) ? 'full' : 'short';
872
873 return self::$localized_months[ $type ][ $month_num ];
874 }
875
876 // DEPRECATED METHODS
877 // @codingStandardsIgnoreStart
878 /**
879 * Deprecated camelCase version of self::date_only
880 *
881 * @param int|string $date The date (timestamp or string).
882 * @param bool $isTimestamp Is $date in timestamp format?
883 *
884 * @return string The date only in DB format.
885 */
886 public static function dateOnly( $date, $isTimestamp = false ) {
887 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::date_only' );
888 return self::date_only( $date, $isTimestamp );
889 }
890
891 /**
892 * Deprecated camelCase version of self::time_only
893 *
894 * @param string $date The date.
895 *
896 * @return string The time only in DB format.
897 */
898 public static function timeOnly( $date ) {
899 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::time_only' );
900 return self::time_only( $date );
901 }
902
903 /**
904 * Deprecated camelCase version of self::hour_only
905 *
906 * @param string $date The date.
907 *
908 * @return string The hour only.
909 */
910 public static function hourOnly( $date ) {
911 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::hour_only' );
912 return self::hour_only( $date );
913 }
914
915 /**
916 * Deprecated camelCase version of self::minutes_only
917 *
918 * @param string $date The date.
919 *
920 * @return string The minute only.
921 */
922 public static function minutesOnly( $date ) {
923 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::minutes_only' );
924 return self::minutes_only( $date );
925 }
926
927 /**
928 * Deprecated camelCase version of self::meridian_only
929 *
930 * @param string $date The date.
931 *
932 * @return string The meridian only in DB format.
933 */
934 public static function meridianOnly( $date ) {
935 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::meridian_only' );
936 return self::meridian_only( $date );
937 }
938
939 /**
940 * Returns the end of a given day.
941 *
942 * @deprecated since 3.10 - use tribe_event_end_of_day()
943 * @todo remove in 4.1
944 *
945 * @param int|string $date The date (timestamp or string).
946 * @param bool $isTimestamp Is $date in timestamp format?
947 *
948 * @return string The date and time of the end of a given day
949 */
950 public static function endOfDay( $date, $isTimestamp = false ) {
951 _deprecated_function( __METHOD__, '3.10', 'tribe_event_end_of_day' );
952
953 if ( $isTimestamp ) {
954 $date = date( self::DBDATEFORMAT, $date );
955 }
956
957 return tribe_event_end_of_day( $date, self::DBDATETIMEFORMAT );
958 }
959
960 /**
961 * Returns the beginning of a given day.
962 *
963 * @deprecated since 3.10
964 * @todo remove in 4.1
965 *
966 * @param int|string $date The date (timestamp or string).
967 * @param bool $isTimestamp Is $date in timestamp format?
968 *
969 * @return string The date and time of the beginning of a given day.
970 */
971 public static function beginningOfDay( $date, $isTimestamp = false ) {
972 _deprecated_function( __METHOD__, '3.10', 'tribe_event_beginning_of_day' );
973
974 if ( $isTimestamp ) {
975 $date = date( self::DBDATEFORMAT, $date );
976 }
977
978 return tribe_event_beginning_of_day( $date, self::DBDATETIMEFORMAT );
979 }
980
981 /**
982 * Deprecated camelCase version of self::time_between
983 *
984 * @param string $date1 The first date.
985 * @param string $date2 The second date.
986 *
987 * @return int The number of seconds between the dates.
988 */
989 public static function timeBetween( $date1, $date2 ) {
990 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::time_between' );
991 return self::time_between( $date1, $date2 );
992 }
993
994 /**
995 * Deprecated camelCase version of self::date_diff
996 *
997 * @param string $date1 The first date.
998 * @param string $date2 The second date.
999 *
1000 * @return int The number of days between two dates.
1001 */
1002 public static function dateDiff( $date1, $date2 ) {
1003 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::date_diff' );
1004 return self::date_diff( $date1, $date2 );
1005 }
1006
1007 /**
1008 * Deprecated camelCase version of self::get_last_day_of_month
1009 *
1010 * @param int $timestamp THe timestamp.
1011 *
1012 * @return string The last day of the month.
1013 */
1014 public static function getLastDayOfMonth( $timestamp ) {
1015 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::get_last_day_of_month' );
1016 return self::get_last_day_of_month( $timestamp );
1017 }
1018
1019 /**
1020 * Deprecated camelCase version of self::is_weekday
1021 *
1022 * @param int $curDate A timestamp.
1023 *
1024 * @return bool If the timestamp is a weekday.
1025 */
1026 public static function isWeekday( $curdate ) {
1027 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_weekday' );
1028 return self::is_weekday( $curdate );
1029 }
1030
1031 /**
1032 * Deprecated camelCase version of self::is_weekend
1033 *
1034 * @param int $curDate A timestamp.
1035 *
1036 * @return bool If the timestamp is a weekend.
1037 */
1038 public static function isWeekend( $curdate ) {
1039 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_weekend' );
1040 return self::is_weekend( $curdate );
1041 }
1042
1043 /**
1044 * Deprecated camelCase version of self::get_last_day_of_week_in_month
1045 *
1046 * @param int $curdate A timestamp.
1047 * @param int $day_of_week The index of the day of the week.
1048 *
1049 * @return int The timestamp of the date that fits the qualifications.
1050 */
1051 public static function getLastDayOfWeekInMonth( $curdate, $day_of_week ) {
1052 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::get_last_day_of_week_in_month' );
1053 return self::get_last_day_of_week_in_month( $curdate, $day_of_week );
1054 }
1055
1056 /**
1057 * Deprecated camelCase version of self::get_first_day_of_week_in_month
1058 *
1059 * @param int $curdate A timestamp.
1060 * @param int $day_of_week The index of the day of the week.
1061 *
1062 * @return int The timestamp of the date that fits the qualifications.
1063 */
1064 public static function getFirstDayOfWeekInMonth( $curdate, $day_of_week ) {
1065 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::get_fist_day_of_week_in_month' );
1066 return self::get_first_day_of_week_in_month( $curdate, $day_of_week );
1067 }
1068
1069 /**
1070 * Deprecated camelCase version of self::number_to_ordinal
1071 *
1072 * @param int $number A number.
1073 *
1074 * @return string The ordinal for that number.
1075 */
1076 public static function numberToOrdinal( $number ) {
1077 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::number_to_ordinal' );
1078 return self::number_to_ordinal( $number );
1079 }
1080
1081 /**
1082 * Deprecated camelCase version of self::is_timestamp
1083 *
1084 * @param $timestamp
1085 *
1086 * @return bool
1087 */
1088 public static function isTimestamp( $timestamp ) {
1089 _deprecated_function( __METHOD__, '3.11', __CLASS__ . '::is_timestamp' );
1090 return self::is_timestamp( $timestamp );
1091 }
1092
1093 /**
1094 * Gets the timestamp of a day in week, month and year context.
1095 *
1096 * Kudos to [icedwater StackOverflow user](http://stackoverflow.com/users/1091386/icedwater) in
1097 * [his answer](http://stackoverflow.com/questions/924246/get-the-first-or-last-friday-in-a-month).
1098 *
1099 * Usage examples:
1100 * "The second Wednesday of March 2015" - `get_day_timestamp( 3, 2, 3, 2015, 1)`
1101 * "The last Friday of December 2015" - `get_day_timestamp( 5, 1, 12, 2015, -1)`
1102 * "The first Monday of April 2016 - `get_day_timestamp( 1, 1, 4, 2016, 1)`
1103 * "The penultimate Thursday of January 2012" - `get_day_timestamp( 4, 2, 1, 2012, -1)`
1104 *
1105 * @param int $day_of_week The day representing the number in the week, Monday is `1`, Tuesday is `2`, Sunday is `7`
1106 * @param int $week_in_month The week number in the month; first week is `1`, second week is `2`; when direction is reverse
1107 * then `1` is last week of the month, `2` is penultimate week of the month and so on.
1108 * @param int $month The month number in the year, January is `1`
1109 * @param int $year The year number, e.g. "2015"
1110 * @param int $week_direction Either `1` or `-1`; the direction for the search referring to the week, defaults to `1`
1111 * to specify weeks in natural order so:
1112 * $week_direction `1` and $week_in_month `1` means "first week of the month"
1113 * $week_direction `1` and $week_in_month `3` means "third week of the month"
1114 * $week_direction `-1` and $week_in_month `1` means "last week of the month"
1115 * $week_direction `-1` and $week_in_month `2` means "penultimmate week of the month"
1116 *
1117 * @return int The day timestamp
1118 */
1119 public static function get_weekday_timestamp( $day_of_week, $week_in_month, $month, $year, $week_direction = 1 ) {
1120 if (
1121 ! (
1122 is_numeric( $day_of_week )
1123 && is_numeric( $week_in_month )
1124 && is_numeric( $month )
1125 && is_numeric( $year )
1126 && is_numeric( $week_direction )
1127 && in_array( $week_direction, array( - 1, 1 ) )
1128 )
1129 ) {
1130 return false;
1131 }
1132
1133 if ( $week_direction > 0 ) {
1134 $startday = 1;
1135 } else {
1136 $startday = date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
1137 }
1138
1139 $start = mktime( 0, 0, 0, $month, $startday, $year );
1140 $weekday = date( 'N', $start );
1141
1142 if ( $week_direction * $day_of_week >= $week_direction * $weekday ) {
1143 $offset = - $week_direction * 7;
1144 } else {
1145 $offset = 0;
1146 }
1147
1148 $offset += $week_direction * ( $week_in_month * 7 ) + ( $day_of_week - $weekday );
1149
1150 return mktime( 0, 0, 0, $month, $startday + $offset, $year );
1151 }
1152
1153 /**
1154 * Unescapes date format strings to be used in functions like `date`.
1155 *
1156 * Double escaping happens when storing a date format in the database.
1157 *
1158 * @param mixed $date_format A date format string.
1159 *
1160 * @return mixed Either the original input or an unescaped date format string.
1161 */
1162 public static function unescape_date_format( $date_format ) {
1163 if ( ! is_string( $date_format ) ) {
1164 return $date_format;
1165 }
1166
1167 // Why so simple? Let's handle other cases as those come up. We have tests in place!
1168 return str_replace( '\\\\', '\\', $date_format );
1169 }
1170 }
1171
1172 }
1173