PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / trunk
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution vtrunk
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
← All changes | app/Services/DateTimeHelper.php +151 -18 1.5.01trunk View file →
@@ -55,18 +55,45 @@
55 55
56 56 public static function getTimeZone()
57 57 {
58 58 $timeZone = wp_timezone_string();
59 + if (!$timeZone || !in_array($timeZone, \DateTimeZone::listIdentifiers())) {
60 + $timeZone = 'UTC';
61 + }
59 62
60 - if (!in_array($timeZone, \DateTimeZone::listIdentifiers())) {
61 - $timeZone = 'UTC';
63 + return $timeZone;
64 + }
65 +
66 + public static function guessTimeZone()
67 + {
68 + $timeZone = self::getTimeZone();
69 +
70 + if (isset($_COOKIE['fluent_booking_user_timezone'])) {
71 + $timeZone = sanitize_text_field(wp_unslash($_COOKIE['fluent_booking_user_timezone']));
62 72 }
63 73
64 74 return $timeZone;
65 75 }
66 76
77 + public static function getValidatedTimeZone($requestedTimeZone)
78 + {
79 + static $cached = [];
80 + if (isset($cached[$requestedTimeZone])) {
81 + return $cached[$requestedTimeZone];
82 + }
83 +
84 + if (!in_array($requestedTimeZone, \DateTimeZone::listIdentifiers())) {
85 + $requestedTimeZone = apply_filters('fluent_booking/fallback_timezone', self::getTimeZone(), $requestedTimeZone);
86 + }
87 +
88 + $cached[$requestedTimeZone] = $requestedTimeZone;
89 + return $requestedTimeZone;
90 + }
91 +
67 92 public static function convertToUtc($dateTime, $timezone, $format = 'Y-m-d H:i:s')
68 93 {
94 + $timezone = self::getValidatedTimeZone($timezone);
95 +
69 96 $dateTime = new \DateTime($dateTime, new \DateTimeZone($timezone));
70 97 $dateTime->setTimezone(new \DateTimeZone('UTC'));
71 98 return $dateTime->format($format);
72 99 }
@@ -75,8 +102,9 @@
75 102 {
76 103 $dateTime = new \DateTime($dateTime, new \DateTimeZone('UTC'));
77 104
78 105 if ($timezone != 'UTC') {
106 + $timezone = self::getValidatedTimeZone($timezone);
79 107 $dateTime->setTimezone(new \DateTimeZone($timezone));
80 108 }
81 109
82 110 return $dateTime->format($format);
@@ -91,8 +119,11 @@
91 119 if ($date) {
92 120 $dateTime = gmdate('Y-m-d H:i', strtotime($date . ' ' . gmdate('H:i', strtotime($dateTime)))); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
93 121 }
94 122
123 + $fromTimeZone = self::getValidatedTimeZone($fromTimeZone);
124 + $toTimeZone = self::getValidatedTimeZone($toTimeZone);
125 +
95 126 $dateTime = new \DateTime($dateTime, new \DateTimeZone($fromTimeZone));
96 127 $dateTime->setTimezone(new \DateTimeZone($toTimeZone));
97 128 return $dateTime->format($format);
98 129 }
@@ -106,8 +137,10 @@
106 137 }
107 138
108 139 public static function convertToIso($dateTime, $fromTimeZone = 'UTC')
109 140 {
141 + $fromTimeZone = self::getValidatedTimeZone($fromTimeZone);
142 +
110 143 $dateTime = new \DateTime($dateTime, new \DateTimeZone($fromTimeZone));
111 144 return $dateTime->format('Y-m-d\TH:i:s\Z');
112 145 }
113 146
@@ -112,15 +145,28 @@
112 145 }
113 146
114 147 public static function convertFromIso($dateTime, $toTimeZone = 'UTC')
115 148 {
149 + $toTimeZone = self::getValidatedTimeZone($toTimeZone);
116 150 $dateTime = new \DateTime($dateTime, new \DateTimeZone('UTC'));
117 151 $dateTime->setTimezone(new \DateTimeZone($toTimeZone));
118 152 return $dateTime->format('Y-m-d H:i:s');
119 153 }
120 154
155 + public static function getIsoDurationInMinutes($duration)
156 + {
157 + if (!$duration) {
158 + return 0;
159 + }
160 +
161 + $duration = new \DateInterval($duration);
162 +
163 + return ($duration->d * 24 * 60) + ($duration->h * 60) + ($duration->i) + ($duration->s / 60);
164 + }
165 +
121 166 public static function getTimestamp($timezone = 'UTC')
122 167 {
168 + $timezone = self::getValidatedTimeZone($timezone);
123 169 $dateTime = new \DateTime(gmdate('Y-m-d H:i:s'), new \DateTimeZone('UTC')); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
124 170 $dateTime->setTimezone(new \DateTimeZone($timezone));
125 171 $date = $dateTime->format('Y-m-d H:i:s');
126 172 return strtotime($date);
@@ -128,32 +174,42 @@
128 174
129 175 public static function formatToLocale($dateTime, $for = 'date')
130 176 {
131 177 // $for can be date | date_time | time
132 - $dateFormat = get_option('date_format');
178 + $dateFormat = (string) get_option('date_format', '');
133 179
134 180 if ($for == 'date_time') {
135 - $dateFormat .= ' ' . get_option('time_format');
181 + $dateFormat .= ' ' . (string) get_option('time_format', '');
136 182 } elseif ($for == 'time') {
137 - $dateFormat = get_option('time_format');
183 + $dateFormat = (string) get_option('time_format', '');
138 184 }
139 185
140 186 return date_i18n($dateFormat, strtotime($dateTime)); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
141 187 }
142 188
189 + public static function getFormattedDate($date, $from = '', $to = 'Y-m-d')
190 + {
191 + if (!$from) {
192 + $from = (string) get_option('date_format', '');
193 + }
194 +
195 + $date = \DateTime::createFromFormat($from, $date);
196 + return $date ? $date->format($to) : '';
197 + }
198 +
143 199 public static function getAvailableDateFormats()
144 200 {
145 201 $dateFormats = apply_filters('fluent_booking/available_date_formats', [
146 - 'm/d/Y' => 'm/d/Y - (Ex: 05/20/2024)', // USA
147 - 'd/m/Y' => 'd/m/Y - (Ex: 20/05/2024)', // Canada, UK
148 - 'd.m.Y' => 'd.m.Y - (Ex: 20.05.2024)', // Germany
149 - 'n/j/y' => 'n/j/y - (Ex: 5/20/24)',
150 - 'm/d/y' => 'm/d/y - (Ex: 05/20/24)',
151 - 'M/d/Y' => 'M/d/Y - (Ex: May/20/2024)',
152 - 'y/m/d' => 'y/m/d - (Ex: 24/05/20)',
153 - 'Y-m-d' => 'Y-m-d - (Ex: 2024-05-20)',
154 - 'd-M-y' => 'd-M-y - (Ex: 20-May-24)',
155 - 'F j, Y' => 'F j, Y - (Ex: May 20, 2024)'
202 + 'm/d/Y' => 'm/d/Y - (Ex: 05/20/2024)', // USA
203 + 'd/m/Y' => 'd/m/Y - (Ex: 20/05/2024)', // Canada, UK
204 + 'd.m.Y' => 'd.m.Y - (Ex: 20.05.2024)', // Germany
205 + 'n/j/y' => 'n/j/y - (Ex: 5/20/24)',
206 + 'm/d/y' => 'm/d/y - (Ex: 05/20/24)',
207 + 'M/d/Y' => 'M/d/Y - (Ex: May/20/2024)',
208 + 'y/m/d' => 'y/m/d - (Ex: 24/05/20)',
209 + 'Y-m-d' => 'Y-m-d - (Ex: 2024-05-20)',
210 + 'd-M-y' => 'd-M-y - (Ex: 20-May-24)',
211 + 'F j, Y' => 'F j, Y - (Ex: May 20, 2024)'
156 212 ]);
157 213
158 214 $formatted = [];
159 215 foreach ($dateFormats as $format => $label) {
@@ -164,8 +220,21 @@
164 220 }
165 221 return $formatted;
166 222 }
167 223
224 + public static function getFormattedEventTime($eventTime)
225 + {
226 + $timeZone = self::guessTimeZone();
227 +
228 + $convertedTime = self::convertToTimeZone($eventTime, 'UTC', $timeZone);
229 +
230 + $eventTime = self::formatToLocale($convertedTime, 'time');
231 +
232 + $eventDate = self::formatToLocale($convertedTime, 'date');
233 +
234 + return $eventTime . ', ' . $eventDate . ' (' . $timeZone . ')';
235 + }
236 +
168 237 public static function convertPhpDateToDayJSFormay($phpFormat)
169 238 {
170 239 // Mapping PHP date format characters to Day.js format characters
171 240 $replacements = [
@@ -229,12 +298,12 @@
229 298 $char = $phpFormat[$i];
230 299
231 300 // Check if the character is escaped
232 301 if ($char === "\\") {
233 - // Add the next character to the result as is, without mapping
302 + // Day.js escapes literal text with square brackets, not backslashes
234 303 $i++;
235 304 if ($i < strlen($phpFormat)) {
236 - $dayjsFormat .= "\\" . $phpFormat[$i];
305 + $dayjsFormat .= "[" . $phpFormat[$i] . "]";
237 306 }
238 307 continue;
239 308 }
240 309
@@ -266,8 +335,9 @@
266 335 }
267 336
268 337 public static function getTodayDate($timezone = 'UTC', $format = 'Y-m-d')
269 338 {
339 + $timezone = self::getValidatedTimeZone($timezone);
270 340 $dateTime = new \DateTime('now', new \DateTimeZone($timezone));
271 341 return $dateTime->format($format);
272 342 }
273 343
@@ -272,8 +342,11 @@
272 342 }
273 343
274 344 public static function getDayDifference($dateTime, $fromTimeZone, $toTimeZone, $refDate = 'now')
275 345 {
346 + $fromTimeZone = self::getValidatedTimeZone($fromTimeZone);
347 + $toTimeZone = self::getValidatedTimeZone($toTimeZone);
348 +
276 349 if ($refDate != 'now') {
277 350 $dateTime = gmdate('Y-m-d H:i', strtotime($refDate . ' ' . gmdate('H:i', strtotime($dateTime)))); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
278 351 }
279 352
@@ -279,9 +352,9 @@
279 352
280 353 $currentDate = new \DateTime($refDate, new \DateTimeZone($fromTimeZone));
281 354
282 355 $originalDateTime = new \DateTime($dateTime, new \DateTimeZone($fromTimeZone));
283 -
356 +
284 357 $originalDateTime->setTimezone(new \DateTimeZone($toTimeZone));
285 358
286 359 return $originalDateTime->format('z') - $currentDate->format('z');
287 360 }
@@ -287,8 +360,9 @@
287 360 }
288 361
289 362 public static function getDaylightSavingTime($timezone)
290 363 {
364 + $timezone = self::getValidatedTimeZone($timezone);
291 365 $timezone = new \DateTimeZone($timezone);
292 366 $dateTime = new \DateTime('2024-01-01', $timezone);
293 367
294 368 $currentOffset = $timezone->getOffset($dateTime);
@@ -307,11 +381,70 @@
307 381 if (!$dateTime || !$timezone) {
308 382 return false;
309 383 }
310 384
385 + $timezone = self::getValidatedTimeZone($timezone);
386 +
311 387 $dateTimeObject = new \DateTime($dateTime, new \DateTimeZone($timezone));
312 388
313 389 $isDstActive = $dateTimeObject->format('I');
314 390
391 + if ($timezone == 'Europe/Dublin') {
392 + return !$isDstActive;
393 + }
394 +
315 395 return $isDstActive;
396 + }
397 +
398 + public static function getI18nDateTimeConfig()
399 + {
400 + return apply_filters('fluent_booking/i18n_date_time_config', [
401 + 'weekdays' => array(
402 + 'sunday' => _x('Sunday', 'calendar day full', 'fluent-booking'),
403 + 'monday' => _x('Monday', 'calendar day full', 'fluent-booking'),
404 + 'tuesday' => _x('Tuesday', 'calendar day full', 'fluent-booking'),
405 + 'wednesday' => _x('Wednesday', 'calendar day full', 'fluent-booking'),
406 + 'thursday' => _x('Thursday', 'calendar day full', 'fluent-booking'),
407 + 'friday' => _x('Friday', 'calendar day full', 'fluent-booking'),
408 + 'saturday' => _x('Saturday', 'calendar day full', 'fluent-booking'),
409 + ),
410 + 'months' => array(
411 + 'January' => _x('January', 'calendar month name full', 'fluent-booking'),
412 + 'February' => _x('February', 'calendar month name full', 'fluent-booking'),
413 + 'March' => _x('March', 'calendar month name full', 'fluent-booking'),
414 + 'April' => _x('April', 'calendar month name full', 'fluent-booking'),
415 + 'May' => _x('May', 'calendar month name full', 'fluent-booking'),
416 + 'June' => _x('June', 'calendar month name full', 'fluent-booking'),
417 + 'July' => _x('July', 'calendar month name full', 'fluent-booking'),
418 + 'August' => _x('August', 'calendar month name full', 'fluent-booking'),
419 + 'September' => _x('September', 'calendar month name full', 'fluent-booking'),
420 + 'October' => _x('October', 'calendar month name full', 'fluent-booking'),
421 + 'November' => _x('November', 'calendar month name full', 'fluent-booking'),
422 + 'December' => _x('December', 'calendar month name full', 'fluent-booking')
423 + ),
424 + 'weekdaysShort' => array(
425 + 'sun' => _x('Sun', 'calendar day short', 'fluent-booking'),
426 + 'mon' => _x('Mon', 'calendar day short', 'fluent-booking'),
427 + 'tue' => _x('Tue', 'calendar day short', 'fluent-booking'),
428 + 'wed' => _x('Wed', 'calendar day short', 'fluent-booking'),
429 + 'thu' => _x('Thu', 'calendar day short', 'fluent-booking'),
430 + 'fri' => _x('Fri', 'calendar day short', 'fluent-booking'),
431 + 'sat' => _x('Sat', 'calendar day short', 'fluent-booking')
432 + ),
433 + 'monthsShort' => array(
434 + 'jan' => _x('Jan', 'calendar month name short', 'fluent-booking'),
435 + 'feb' => _x('Feb', 'calendar month name short', 'fluent-booking'),
436 + 'mar' => _x('Mar', 'calendar month name short', 'fluent-booking'),
437 + 'apr' => _x('Apr', 'calendar month name short', 'fluent-booking'),
438 + 'may' => _x('May', 'calendar month name short', 'fluent-booking'),
439 + 'jun' => _x('Jun', 'calendar month name short', 'fluent-booking'),
440 + 'jul' => _x('Jul', 'calendar month name short', 'fluent-booking'),
441 + 'aug' => _x('Aug', 'calendar month name short', 'fluent-booking'),
442 + 'sep' => _x('Sep', 'calendar month name short', 'fluent-booking'),
443 + 'oct' => _x('Oct', 'calendar month name short', 'fluent-booking'),
444 + 'nov' => _x('Nov', 'calendar month name short', 'fluent-booking'),
445 + 'dec' => _x('Dec', 'calendar month name short', 'fluent-booking')
446 + ),
447 + 'numericSystem' => _x('0_1_2_3_4_5_6_7_8_9', 'calendar numeric system - Sequence must need to maintained', 'fluent-booking'),
448 + ]);
316 449 }
317 450 }