Completed
Branch BUG-10626-dst-unit-test (350067)
by
unknown
95:29 queued 84:57
created
core/helpers/EEH_DTT_Helper.helper.php 2 patches
Spacing   +40 added lines, -41 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-if (! defined('EVENT_ESPRESSO_VERSION')) {
2
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
3 3
     exit('NO direct script access allowed');
4 4
 }
5 5
 
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
             new DateTimeZone($timezone_string);
75 75
         } catch (Exception $e) {
76 76
             // sometimes we take exception to exceptions
77
-            if (! $throw_error) {
77
+            if ( ! $throw_error) {
78 78
                 return false;
79 79
             }
80 80
             throw new EE_Error(
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
             }
159 159
         }
160 160
         $offset = get_option('gmt_offset');
161
-        return (int)($offset * HOUR_IN_SECONDS);
161
+        return (int) ($offset * HOUR_IN_SECONDS);
162 162
     }
163 163
 
164 164
 
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
     public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
174 174
     {
175 175
         //make sure $gmt_offset is int
176
-        $gmt_offset = (int)$gmt_offset;
176
+        $gmt_offset = (int) $gmt_offset;
177 177
         switch ($gmt_offset) {
178 178
             //-12
179 179
             case -43200:
@@ -346,7 +346,7 @@  discard block
 block discarded – undo
346 346
     public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
347 347
     {
348 348
         $transitions = self::get_timezone_transitions($date_time_zone, $time);
349
-        if (! isset($transitions['offset'])) {
349
+        if ( ! isset($transitions['offset'])) {
350 350
             throw new DomainException();
351 351
         }
352 352
         return $transitions['offset'];
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
     public static function timezone_select_input($timezone_string = '')
361 361
     {
362 362
         // get WP date time format
363
-        $datetime_format = get_option('date_format') . ' ' . get_option('time_format');
363
+        $datetime_format = get_option('date_format').' '.get_option('time_format');
364 364
         // if passed a value, then use that, else get WP option
365 365
         $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string');
366 366
         // check if the timezone is valid but don't throw any errors if it isn't
@@ -372,9 +372,9 @@  discard block
 block discarded – undo
372 372
             // Create a UTC+- zone if no timezone string exists
373 373
             $check_zone_info = false;
374 374
             if ($gmt_offset > 0) {
375
-                $timezone_string = 'UTC+' . $gmt_offset;
375
+                $timezone_string = 'UTC+'.$gmt_offset;
376 376
             } elseif ($gmt_offset < 0) {
377
-                $timezone_string = 'UTC' . $gmt_offset;
377
+                $timezone_string = 'UTC'.$gmt_offset;
378 378
             } else {
379 379
                 $timezone_string = 'UTC';
380 380
             }
@@ -396,11 +396,11 @@  discard block
 block discarded – undo
396 396
                 __('%1$sUTC%2$s time is %3$s'),
397 397
                 '<abbr title="Coordinated Universal Time">',
398 398
                 '</abbr>',
399
-                '<code>' . date_i18n($datetime_format, false, true) . '</code>'
399
+                '<code>'.date_i18n($datetime_format, false, true).'</code>'
400 400
             );
401 401
             ?></span>
402
-        <?php if (! empty($timezone_string) || ! empty($gmt_offset)) : ?>
403
-        <br/><span><?php printf(__('Local time is %1$s'), '<code>' . date_i18n($datetime_format) . '</code>'); ?></span>
402
+        <?php if ( ! empty($timezone_string) || ! empty($gmt_offset)) : ?>
403
+        <br/><span><?php printf(__('Local time is %1$s'), '<code>'.date_i18n($datetime_format).'</code>'); ?></span>
404 404
     <?php endif; ?>
405 405
 
406 406
         <?php if ($check_zone_info && $timezone_string) : ?>
@@ -433,11 +433,10 @@  discard block
 block discarded – undo
433 433
 
434 434
                 if ($found) {
435 435
                     $message = $tr['isdst'] ?
436
-                        __(' Daylight saving time begins on: %s.') :
437
-                        __(' Standard time begins  on: %s.');
436
+                        __(' Daylight saving time begins on: %s.') : __(' Standard time begins  on: %s.');
438 437
                     // Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n().
439 438
                     printf($message,
440
-                        '<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >');
439
+                        '<code >'.date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])).'</code >');
441 440
                 } else {
442 441
                     _e('This timezone does not observe daylight saving time.');
443 442
                 }
@@ -465,13 +464,13 @@  discard block
 block discarded – undo
465 464
      */
466 465
     public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
467 466
     {
468
-        $unix_timestamp  = $unix_timestamp === 0 ? time() : (int)$unix_timestamp;
467
+        $unix_timestamp  = $unix_timestamp === 0 ? time() : (int) $unix_timestamp;
469 468
         $timezone_string = self::get_valid_timezone_string($timezone_string);
470 469
         $TimeZone        = new DateTimeZone($timezone_string);
471 470
 
472
-        $DateTime = new DateTime('@' . $unix_timestamp, $TimeZone);
471
+        $DateTime = new DateTime('@'.$unix_timestamp, $TimeZone);
473 472
         $offset   = timezone_offset_get($TimeZone, $DateTime);
474
-        return (int)$DateTime->format('U') + (int)$offset;
473
+        return (int) $DateTime->format('U') + (int) $offset;
475 474
     }
476 475
 
477 476
 
@@ -554,7 +553,7 @@  discard block
 block discarded – undo
554 553
      */
555 554
     protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
556 555
     {
557
-        if (! $DateTime instanceof DateTime) {
556
+        if ( ! $DateTime instanceof DateTime) {
558 557
             throw new EE_Error(
559 558
                 sprintf(
560 559
                     __('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
@@ -564,25 +563,25 @@  discard block
 block discarded – undo
564 563
         }
565 564
         switch ($period) {
566 565
             case 'years' :
567
-                $value = 'P' . $value . 'Y';
566
+                $value = 'P'.$value.'Y';
568 567
                 break;
569 568
             case 'months' :
570
-                $value = 'P' . $value . 'M';
569
+                $value = 'P'.$value.'M';
571 570
                 break;
572 571
             case 'weeks' :
573
-                $value = 'P' . $value . 'W';
572
+                $value = 'P'.$value.'W';
574 573
                 break;
575 574
             case 'days' :
576
-                $value = 'P' . $value . 'D';
575
+                $value = 'P'.$value.'D';
577 576
                 break;
578 577
             case 'hours' :
579
-                $value = 'PT' . $value . 'H';
578
+                $value = 'PT'.$value.'H';
580 579
                 break;
581 580
             case 'minutes' :
582
-                $value = 'PT' . $value . 'M';
581
+                $value = 'PT'.$value.'M';
583 582
                 break;
584 583
             case 'seconds' :
585
-                $value = 'PT' . $value . 'S';
584
+                $value = 'PT'.$value.'S';
586 585
                 break;
587 586
         }
588 587
         switch ($operand) {
@@ -610,7 +609,7 @@  discard block
 block discarded – undo
610 609
      */
611 610
     protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
612 611
     {
613
-        if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
612
+        if ( ! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
614 613
             throw new EE_Error(
615 614
                 sprintf(
616 615
                     __('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
@@ -714,7 +713,7 @@  discard block
 block discarded – undo
714 713
                 'date' => $date_format['js'],
715 714
                 'time' => $time_format['js'],
716 715
             ),
717
-            'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
716
+            'moment' => $date_format['moment'].' '.$time_format['moment'],
718 717
         );
719 718
     }
720 719
 
@@ -733,7 +732,7 @@  discard block
 block discarded – undo
733 732
          *
734 733
          * @var array
735 734
          */
736
-        $symbols_map      = array(
735
+        $symbols_map = array(
737 736
             // Day
738 737
             //01
739 738
             'd' => array(
@@ -891,7 +890,7 @@  discard block
 block discarded – undo
891 890
                     $jquery_ui_format .= $format_string[$i];
892 891
                     $moment_format .= $format_string[$i];
893 892
                 } else {
894
-                    $jquery_ui_format .= '\'' . $format_string[$i];
893
+                    $jquery_ui_format .= '\''.$format_string[$i];
895 894
                     $moment_format .= $format_string[$i];
896 895
                 }
897 896
                 $escaping = true;
@@ -961,7 +960,7 @@  discard block
 block discarded – undo
961 960
     {
962 961
 
963 962
         if (
964
-            (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) ||
963
+            ( ! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) ||
965 964
             ($date_1->format(EE_Datetime_Field::mysql_time_format) != '00:00:00' || $date_2->format(EE_Datetime_Field::mysql_time_format) != '00:00:00')
966 965
         ) {
967 966
             return false;
@@ -993,8 +992,8 @@  discard block
 block discarded – undo
993 992
          */
994 993
         $offset         = $DateTimeZone instanceof DateTimeZone ? ($DateTimeZone->getOffset(new DateTime('now'))) / HOUR_IN_SECONDS : get_option('gmt_offset');
995 994
         $query_interval = $offset < 0
996
-            ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
997
-            : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
995
+            ? 'DATE_SUB('.$field_for_interval.', INTERVAL '.$offset * -1.' HOUR)'
996
+            : 'DATE_ADD('.$field_for_interval.', INTERVAL '.$offset.' HOUR)';
998 997
         return $query_interval;
999 998
     }
1000 999
 
@@ -1010,16 +1009,16 @@  discard block
 block discarded – undo
1010 1009
     public static function get_timezone_string_for_display()
1011 1010
     {
1012 1011
         $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
1013
-        if (! empty($pretty_timezone)) {
1012
+        if ( ! empty($pretty_timezone)) {
1014 1013
             return esc_html($pretty_timezone);
1015 1014
         }
1016 1015
         $timezone_string = get_option('timezone_string');
1017 1016
         if ($timezone_string) {
1018 1017
             static $mo_loaded = false;
1019 1018
             // Load translations for continents and cities just like wp_timezone_choice does
1020
-            if (! $mo_loaded) {
1019
+            if ( ! $mo_loaded) {
1021 1020
                 $locale = get_locale();
1022
-                $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
1021
+                $mofile = WP_LANG_DIR.'/continents-cities-'.$locale.'.mo';
1023 1022
                 load_textdomain('continents-cities', $mofile);
1024 1023
                 $mo_loaded = true;
1025 1024
             }
@@ -1040,16 +1039,16 @@  discard block
 block discarded – undo
1040 1039
         } else {
1041 1040
             $prefix = '';
1042 1041
         }
1043
-        $parts = explode('.', (string)$gmt_offset);
1042
+        $parts = explode('.', (string) $gmt_offset);
1044 1043
         if (count($parts) === 1) {
1045 1044
             $parts[1] = '00';
1046 1045
         } else {
1047 1046
             //convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
1048 1047
             //to minutes, eg 30 or 15, respectively
1049
-            $hour_fraction = (float)('0.' . $parts[1]);
1050
-            $parts[1]      = (string)$hour_fraction * 60;
1048
+            $hour_fraction = (float) ('0.'.$parts[1]);
1049
+            $parts[1]      = (string) $hour_fraction * 60;
1051 1050
         }
1052
-        return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
1051
+        return sprintf(__('UTC%1$s', 'event_espresso'), $prefix.implode(':', $parts));
1053 1052
     }
1054 1053
 
1055 1054
 
@@ -1075,7 +1074,7 @@  discard block
 block discarded – undo
1075 1074
      */
1076 1075
     public static function first_of_month_timestamp($month = '')
1077 1076
     {
1078
-        $month = (string)$month;
1077
+        $month = (string) $month;
1079 1078
         $year = '';
1080 1079
         // check if the incoming string has a year in it or not
1081 1080
        if (preg_match('/\b\d{4}\b/', $month, $matches)) {
@@ -1099,7 +1098,7 @@  discard block
 block discarded – undo
1099 1098
 		//before adding to the timestamp.  Why? Because we want tomorrow to be for midnight the next day in THIS timezone
1100 1099
 		//not an offset from midnight in UTC.  So if we're starting with UTC 00:00:00, then we want to make sure the
1101 1100
 		//final timestamp is equivalent to midnight in this timezone as represented in GMT.
1102
-		return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset()*-1);
1101
+		return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1);
1103 1102
 	}
1104 1103
 
1105 1104
 }// end class EEH_DTT_Helper
Please login to merge, or discard this patch.
Indentation   +1047 added lines, -1047 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if (! defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('NO direct script access allowed');
3
+	exit('NO direct script access allowed');
4 4
 }
5 5
 
6 6
 /**
@@ -26,364 +26,364 @@  discard block
 block discarded – undo
26 26
 {
27 27
 
28 28
 
29
-    /**
30
-     * return the timezone set for the WP install
31
-     *
32
-     * @return string valid timezone string for PHP DateTimeZone() class
33
-     */
34
-    public static function get_timezone()
35
-    {
36
-        return EEH_DTT_Helper::get_valid_timezone_string();
37
-    }
38
-
39
-
40
-    /**
41
-     * get_valid_timezone_string
42
-     *    ensures that a valid timezone string is returned
43
-     *
44
-     * @access protected
45
-     * @param string $timezone_string
46
-     * @return string
47
-     * @throws \EE_Error
48
-     */
49
-    public static function get_valid_timezone_string($timezone_string = '')
50
-    {
51
-        // if passed a value, then use that, else get WP option
52
-        $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string');
53
-        // value from above exists, use that, else get timezone string from gmt_offset
54
-        $timezone_string = ! empty($timezone_string) ? $timezone_string : EEH_DTT_Helper::get_timezone_string_from_gmt_offset();
55
-        EEH_DTT_Helper::validate_timezone($timezone_string);
56
-        return $timezone_string;
57
-    }
58
-
59
-
60
-    /**
61
-     * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
62
-     *
63
-     * @static
64
-     * @access public
65
-     * @param  string $timezone_string Timezone string to check
66
-     * @param bool    $throw_error
67
-     * @return bool
68
-     * @throws \EE_Error
69
-     */
70
-    public static function validate_timezone($timezone_string, $throw_error = true)
71
-    {
72
-        // easiest way to test a timezone string is just see if it throws an error when you try to create a DateTimeZone object with it
73
-        try {
74
-            new DateTimeZone($timezone_string);
75
-        } catch (Exception $e) {
76
-            // sometimes we take exception to exceptions
77
-            if (! $throw_error) {
78
-                return false;
79
-            }
80
-            throw new EE_Error(
81
-                sprintf(
82
-                    __('The timezone given (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
83
-                        'event_espresso'),
84
-                    $timezone_string,
85
-                    '<a href="http://www.php.net/manual/en/timezones.php">',
86
-                    '</a>'
87
-                )
88
-            );
89
-        }
90
-        return true;
91
-    }
92
-
93
-
94
-    /**
95
-     * _create_timezone_object_from_timezone_name
96
-     *
97
-     * @access protected
98
-     * @param string $gmt_offset
99
-     * @return string
100
-     */
101
-    public static function get_timezone_string_from_gmt_offset($gmt_offset = '')
102
-    {
103
-        $timezone_string = 'UTC';
104
-        //if there is no incoming gmt_offset, then because WP hooks in on timezone_string, we need to see if that is
105
-        //set because it will override `gmt_offset` via `pre_get_option` filter.  If that's set, then let's just use
106
-        //that!  Otherwise we'll leave timezone_string at the default of 'UTC' before doing other logic.
107
-        if ($gmt_offset === '') {
108
-            //autoloaded so no need to set to a variable.  There will not be multiple hits to the db.
109
-            if (get_option('timezone_string')) {
110
-                return get_option('timezone_string');
111
-            }
112
-        }
113
-        $gmt_offset = $gmt_offset !== '' ? $gmt_offset : get_option('gmt_offset');
114
-        $gmt_offset = (float) $gmt_offset;
115
-
116
-        //if $gmt_offset is 0, then just return UTC
117
-        if ($gmt_offset === (float) 0) {
118
-            return $timezone_string;
119
-        }
120
-
121
-
122
-        if ($gmt_offset !== '') {
123
-            // convert GMT offset to seconds
124
-            $gmt_offset = $gmt_offset * HOUR_IN_SECONDS;
125
-            // although we don't know the TZ abbreviation, we know the UTC offset
126
-            $timezone_string = timezone_name_from_abbr(null, $gmt_offset);
127
-            //only use this timezone_string IF it's current offset matches the given offset
128
-            try {
129
-                $offset = self::get_timezone_offset(new DateTimeZone($timezone_string));
130
-                if ($offset !== $gmt_offset) {
131
-                    $timezone_string = false;
132
-                }
133
-            } catch (Exception $e) {
134
-                $timezone_string = false;
135
-            }
136
-        }
137
-        // better have a valid timezone string by now, but if not, sigh... loop thru  the timezone_abbreviations_list()...
138
-        $timezone_string = $timezone_string !== false
139
-            ? $timezone_string
140
-            : EEH_DTT_Helper::get_timezone_string_from_abbreviations_list($gmt_offset);
141
-        return $timezone_string;
142
-    }
143
-
144
-    /**
145
-     * Gets the site's GMT offset based on either the timezone string
146
-     * (in which case teh gmt offset will vary depending on the location's
147
-     * observance of daylight savings time) or the gmt_offset wp option
148
-     *
149
-     * @return int seconds offset
150
-     */
151
-    public static function get_site_timezone_gmt_offset()
152
-    {
153
-        $timezone_string = get_option('timezone_string');
154
-        if ($timezone_string) {
155
-            try {
156
-                $timezone = new DateTimeZone($timezone_string);
157
-                return $timezone->getOffset(new DateTime()); //in WordPress DateTime defaults to UTC
158
-            } catch (Exception $e) {
159
-            }
160
-        }
161
-        $offset = get_option('gmt_offset');
162
-        return (int)($offset * HOUR_IN_SECONDS);
163
-    }
164
-
165
-
166
-    /**
167
-     * Depending on PHP version, there might not bevalid current timezone strings to match these gmt_offsets in its
168
-     * timezone tables.
169
-     * To get around that, for these fringe timezones we bump them to a known valid offset.
170
-     *
171
-     * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset.
172
-     *
173
-     * @access public
174
-     * @param int $gmt_offset
175
-     * @return int
176
-     */
177
-    public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
178
-    {
179
-        //make sure $gmt_offset is int
180
-        $gmt_offset = (int)$gmt_offset;
181
-        switch ($gmt_offset) {
182
-            //-12
183
-            case -43200:
184
-                $gmt_offset = -39600;
185
-                break;
186
-            //-11.5
187
-            case -41400:
188
-                $gmt_offset = -39600;
189
-                break;
190
-            //-10.5
191
-            case -37800:
192
-                $gmt_offset = -39600;
193
-                break;
194
-            //-8.5
195
-            case -30600:
196
-                $gmt_offset = -28800;
197
-                break;
198
-            //-7.5
199
-            case -27000:
200
-                $gmt_offset = -25200;
201
-                break;
202
-            //-6.5
203
-            case -23400:
204
-                $gmt_offset = -21600;
205
-                break;
206
-            //-5.5
207
-            case -19800:
208
-                $gmt_offset = -18000;
209
-                break;
210
-            //-4.5
211
-            case -16200:
212
-                $gmt_offset = -14400;
213
-                break;
214
-            //-3.5
215
-            case -12600:
216
-                $gmt_offset = -10800;
217
-                break;
218
-            //-2.5
219
-            case -9000:
220
-                $gmt_offset = -7200;
221
-                break;
222
-            //-1.5
223
-            case -5400:
224
-                $gmt_offset = -3600;
225
-                break;
226
-            //-0.5
227
-            case -1800:
228
-                $gmt_offset = 0;
229
-                break;
230
-            //.5
231
-            case 1800:
232
-                $gmt_offset = 3600;
233
-                break;
234
-            //1.5
235
-            case 5400:
236
-                $gmt_offset = 7200;
237
-                break;
238
-            //2.5
239
-            case 9000:
240
-                $gmt_offset = 10800;
241
-                break;
242
-            //3.5
243
-            case 12600:
244
-                $gmt_offset = 14400;
245
-                break;
246
-
247
-            //7.5
248
-            case 27000:
249
-                $gmt_offset = 28800;
250
-                break;
251
-            //8.5
252
-            case 30600:
253
-                $gmt_offset = 31500;
254
-                break;
255
-            //10.5
256
-            case 37800:
257
-                $gmt_offset = 39600;
258
-                break;
259
-            //11.5
260
-            case 41400:
261
-                $gmt_offset = 43200;
262
-                break;
263
-            //12.75
264
-            case 45900:
265
-                $gmt_offset = 46800;
266
-                break;
267
-            //13.75
268
-            case 49500:
269
-                $gmt_offset = 50400;
270
-                break;
271
-        }
272
-        return $gmt_offset;
273
-    }
274
-
275
-
276
-    /**
277
-     * get_timezone_string_from_abbreviations_list
278
-     *
279
-     * @access public
280
-     * @param int  $gmt_offset
281
-     * @param bool $coerce   If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset.
282
-     * @return string
283
-     * @throws \EE_Error
284
-     */
285
-    public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true)
286
-    {
287
-        $abbreviations = timezone_abbreviations_list();
288
-        foreach ($abbreviations as $abbreviation) {
289
-            foreach ($abbreviation as $city) {
290
-                if ($city['offset'] === $gmt_offset && $city['dst'] === false) {
291
-                    try {
292
-                        $offset = self::get_timezone_offset(new DateTimeZone($city['timezone_id']));
293
-                        if ($offset !== $gmt_offset) {
294
-                            continue;
295
-                        } else {
296
-                            return $city['timezone_id'];
297
-                        }
298
-                    } catch (Exception $e) {
299
-                        continue;
300
-                    }
301
-                }
302
-            }
303
-        }
304
-        //if $coerce is true, let's see if we can get a timezone string after the offset is adjusted
305
-        if ($coerce == true) {
306
-            $timezone_string = self::get_timezone_string_from_abbreviations_list(
307
-                self::adjust_invalid_gmt_offsets($gmt_offset),
308
-                false
309
-            );
310
-            if ($timezone_string) {
311
-                return $timezone_string;
312
-            }
313
-        }
314
-        throw new EE_Error(
315
-            sprintf(
316
-                __('The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
317
-                    'event_espresso'),
318
-                $gmt_offset,
319
-                '<a href="http://www.php.net/manual/en/timezones.php">',
320
-                '</a>'
321
-            )
322
-        );
323
-    }
324
-
325
-
326
-
327
-    /**
328
-     * Get Timezone Transitions
329
-     * @param \DateTimeZone $date_time_zone
330
-     * @param null          $time
331
-     * @param bool          $first_only
332
-     * @return array|mixed
333
-     */
334
-    public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
335
-    {
336
-        $time = is_int($time) || $time === null ? $time : strtotime($time);
337
-        $time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
338
-        $transitions = $date_time_zone->getTransitions($time);
339
-        return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
340
-    }
341
-
342
-
343
-    /**
344
-     * Get Timezone Offset for given timezone object.
345
-     * @param \DateTimeZone $date_time_zone
346
-     * @param null          $time
347
-     * @return mixed
348
-     * @throws \DomainException
349
-     */
350
-    public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
351
-    {
352
-        $transitions = self::get_timezone_transitions($date_time_zone, $time);
353
-        if (! isset($transitions['offset'])) {
354
-            throw new DomainException();
355
-        }
356
-        return $transitions['offset'];
357
-    }
358
-
359
-
360
-    /**
361
-     * @access public
362
-     * @param string $timezone_string
363
-     */
364
-    public static function timezone_select_input($timezone_string = '')
365
-    {
366
-        // get WP date time format
367
-        $datetime_format = get_option('date_format') . ' ' . get_option('time_format');
368
-        // if passed a value, then use that, else get WP option
369
-        $timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string');
370
-        // check if the timezone is valid but don't throw any errors if it isn't
371
-        $timezone_string = EEH_DTT_Helper::validate_timezone($timezone_string, false);
372
-        $gmt_offset      = get_option('gmt_offset');
373
-
374
-        $check_zone_info = true;
375
-        if (empty($timezone_string)) {
376
-            // Create a UTC+- zone if no timezone string exists
377
-            $check_zone_info = false;
378
-            if ($gmt_offset > 0) {
379
-                $timezone_string = 'UTC+' . $gmt_offset;
380
-            } elseif ($gmt_offset < 0) {
381
-                $timezone_string = 'UTC' . $gmt_offset;
382
-            } else {
383
-                $timezone_string = 'UTC';
384
-            }
385
-        }
386
-        ?>
29
+	/**
30
+	 * return the timezone set for the WP install
31
+	 *
32
+	 * @return string valid timezone string for PHP DateTimeZone() class
33
+	 */
34
+	public static function get_timezone()
35
+	{
36
+		return EEH_DTT_Helper::get_valid_timezone_string();
37
+	}
38
+
39
+
40
+	/**
41
+	 * get_valid_timezone_string
42
+	 *    ensures that a valid timezone string is returned
43
+	 *
44
+	 * @access protected
45
+	 * @param string $timezone_string
46
+	 * @return string
47
+	 * @throws \EE_Error
48
+	 */
49
+	public static function get_valid_timezone_string($timezone_string = '')
50
+	{
51
+		// if passed a value, then use that, else get WP option
52
+		$timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string');
53
+		// value from above exists, use that, else get timezone string from gmt_offset
54
+		$timezone_string = ! empty($timezone_string) ? $timezone_string : EEH_DTT_Helper::get_timezone_string_from_gmt_offset();
55
+		EEH_DTT_Helper::validate_timezone($timezone_string);
56
+		return $timezone_string;
57
+	}
58
+
59
+
60
+	/**
61
+	 * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
62
+	 *
63
+	 * @static
64
+	 * @access public
65
+	 * @param  string $timezone_string Timezone string to check
66
+	 * @param bool    $throw_error
67
+	 * @return bool
68
+	 * @throws \EE_Error
69
+	 */
70
+	public static function validate_timezone($timezone_string, $throw_error = true)
71
+	{
72
+		// easiest way to test a timezone string is just see if it throws an error when you try to create a DateTimeZone object with it
73
+		try {
74
+			new DateTimeZone($timezone_string);
75
+		} catch (Exception $e) {
76
+			// sometimes we take exception to exceptions
77
+			if (! $throw_error) {
78
+				return false;
79
+			}
80
+			throw new EE_Error(
81
+				sprintf(
82
+					__('The timezone given (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
83
+						'event_espresso'),
84
+					$timezone_string,
85
+					'<a href="http://www.php.net/manual/en/timezones.php">',
86
+					'</a>'
87
+				)
88
+			);
89
+		}
90
+		return true;
91
+	}
92
+
93
+
94
+	/**
95
+	 * _create_timezone_object_from_timezone_name
96
+	 *
97
+	 * @access protected
98
+	 * @param string $gmt_offset
99
+	 * @return string
100
+	 */
101
+	public static function get_timezone_string_from_gmt_offset($gmt_offset = '')
102
+	{
103
+		$timezone_string = 'UTC';
104
+		//if there is no incoming gmt_offset, then because WP hooks in on timezone_string, we need to see if that is
105
+		//set because it will override `gmt_offset` via `pre_get_option` filter.  If that's set, then let's just use
106
+		//that!  Otherwise we'll leave timezone_string at the default of 'UTC' before doing other logic.
107
+		if ($gmt_offset === '') {
108
+			//autoloaded so no need to set to a variable.  There will not be multiple hits to the db.
109
+			if (get_option('timezone_string')) {
110
+				return get_option('timezone_string');
111
+			}
112
+		}
113
+		$gmt_offset = $gmt_offset !== '' ? $gmt_offset : get_option('gmt_offset');
114
+		$gmt_offset = (float) $gmt_offset;
115
+
116
+		//if $gmt_offset is 0, then just return UTC
117
+		if ($gmt_offset === (float) 0) {
118
+			return $timezone_string;
119
+		}
120
+
121
+
122
+		if ($gmt_offset !== '') {
123
+			// convert GMT offset to seconds
124
+			$gmt_offset = $gmt_offset * HOUR_IN_SECONDS;
125
+			// although we don't know the TZ abbreviation, we know the UTC offset
126
+			$timezone_string = timezone_name_from_abbr(null, $gmt_offset);
127
+			//only use this timezone_string IF it's current offset matches the given offset
128
+			try {
129
+				$offset = self::get_timezone_offset(new DateTimeZone($timezone_string));
130
+				if ($offset !== $gmt_offset) {
131
+					$timezone_string = false;
132
+				}
133
+			} catch (Exception $e) {
134
+				$timezone_string = false;
135
+			}
136
+		}
137
+		// better have a valid timezone string by now, but if not, sigh... loop thru  the timezone_abbreviations_list()...
138
+		$timezone_string = $timezone_string !== false
139
+			? $timezone_string
140
+			: EEH_DTT_Helper::get_timezone_string_from_abbreviations_list($gmt_offset);
141
+		return $timezone_string;
142
+	}
143
+
144
+	/**
145
+	 * Gets the site's GMT offset based on either the timezone string
146
+	 * (in which case teh gmt offset will vary depending on the location's
147
+	 * observance of daylight savings time) or the gmt_offset wp option
148
+	 *
149
+	 * @return int seconds offset
150
+	 */
151
+	public static function get_site_timezone_gmt_offset()
152
+	{
153
+		$timezone_string = get_option('timezone_string');
154
+		if ($timezone_string) {
155
+			try {
156
+				$timezone = new DateTimeZone($timezone_string);
157
+				return $timezone->getOffset(new DateTime()); //in WordPress DateTime defaults to UTC
158
+			} catch (Exception $e) {
159
+			}
160
+		}
161
+		$offset = get_option('gmt_offset');
162
+		return (int)($offset * HOUR_IN_SECONDS);
163
+	}
164
+
165
+
166
+	/**
167
+	 * Depending on PHP version, there might not bevalid current timezone strings to match these gmt_offsets in its
168
+	 * timezone tables.
169
+	 * To get around that, for these fringe timezones we bump them to a known valid offset.
170
+	 *
171
+	 * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset.
172
+	 *
173
+	 * @access public
174
+	 * @param int $gmt_offset
175
+	 * @return int
176
+	 */
177
+	public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
178
+	{
179
+		//make sure $gmt_offset is int
180
+		$gmt_offset = (int)$gmt_offset;
181
+		switch ($gmt_offset) {
182
+			//-12
183
+			case -43200:
184
+				$gmt_offset = -39600;
185
+				break;
186
+			//-11.5
187
+			case -41400:
188
+				$gmt_offset = -39600;
189
+				break;
190
+			//-10.5
191
+			case -37800:
192
+				$gmt_offset = -39600;
193
+				break;
194
+			//-8.5
195
+			case -30600:
196
+				$gmt_offset = -28800;
197
+				break;
198
+			//-7.5
199
+			case -27000:
200
+				$gmt_offset = -25200;
201
+				break;
202
+			//-6.5
203
+			case -23400:
204
+				$gmt_offset = -21600;
205
+				break;
206
+			//-5.5
207
+			case -19800:
208
+				$gmt_offset = -18000;
209
+				break;
210
+			//-4.5
211
+			case -16200:
212
+				$gmt_offset = -14400;
213
+				break;
214
+			//-3.5
215
+			case -12600:
216
+				$gmt_offset = -10800;
217
+				break;
218
+			//-2.5
219
+			case -9000:
220
+				$gmt_offset = -7200;
221
+				break;
222
+			//-1.5
223
+			case -5400:
224
+				$gmt_offset = -3600;
225
+				break;
226
+			//-0.5
227
+			case -1800:
228
+				$gmt_offset = 0;
229
+				break;
230
+			//.5
231
+			case 1800:
232
+				$gmt_offset = 3600;
233
+				break;
234
+			//1.5
235
+			case 5400:
236
+				$gmt_offset = 7200;
237
+				break;
238
+			//2.5
239
+			case 9000:
240
+				$gmt_offset = 10800;
241
+				break;
242
+			//3.5
243
+			case 12600:
244
+				$gmt_offset = 14400;
245
+				break;
246
+
247
+			//7.5
248
+			case 27000:
249
+				$gmt_offset = 28800;
250
+				break;
251
+			//8.5
252
+			case 30600:
253
+				$gmt_offset = 31500;
254
+				break;
255
+			//10.5
256
+			case 37800:
257
+				$gmt_offset = 39600;
258
+				break;
259
+			//11.5
260
+			case 41400:
261
+				$gmt_offset = 43200;
262
+				break;
263
+			//12.75
264
+			case 45900:
265
+				$gmt_offset = 46800;
266
+				break;
267
+			//13.75
268
+			case 49500:
269
+				$gmt_offset = 50400;
270
+				break;
271
+		}
272
+		return $gmt_offset;
273
+	}
274
+
275
+
276
+	/**
277
+	 * get_timezone_string_from_abbreviations_list
278
+	 *
279
+	 * @access public
280
+	 * @param int  $gmt_offset
281
+	 * @param bool $coerce   If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset.
282
+	 * @return string
283
+	 * @throws \EE_Error
284
+	 */
285
+	public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true)
286
+	{
287
+		$abbreviations = timezone_abbreviations_list();
288
+		foreach ($abbreviations as $abbreviation) {
289
+			foreach ($abbreviation as $city) {
290
+				if ($city['offset'] === $gmt_offset && $city['dst'] === false) {
291
+					try {
292
+						$offset = self::get_timezone_offset(new DateTimeZone($city['timezone_id']));
293
+						if ($offset !== $gmt_offset) {
294
+							continue;
295
+						} else {
296
+							return $city['timezone_id'];
297
+						}
298
+					} catch (Exception $e) {
299
+						continue;
300
+					}
301
+				}
302
+			}
303
+		}
304
+		//if $coerce is true, let's see if we can get a timezone string after the offset is adjusted
305
+		if ($coerce == true) {
306
+			$timezone_string = self::get_timezone_string_from_abbreviations_list(
307
+				self::adjust_invalid_gmt_offsets($gmt_offset),
308
+				false
309
+			);
310
+			if ($timezone_string) {
311
+				return $timezone_string;
312
+			}
313
+		}
314
+		throw new EE_Error(
315
+			sprintf(
316
+				__('The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
317
+					'event_espresso'),
318
+				$gmt_offset,
319
+				'<a href="http://www.php.net/manual/en/timezones.php">',
320
+				'</a>'
321
+			)
322
+		);
323
+	}
324
+
325
+
326
+
327
+	/**
328
+	 * Get Timezone Transitions
329
+	 * @param \DateTimeZone $date_time_zone
330
+	 * @param null          $time
331
+	 * @param bool          $first_only
332
+	 * @return array|mixed
333
+	 */
334
+	public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
335
+	{
336
+		$time = is_int($time) || $time === null ? $time : strtotime($time);
337
+		$time = preg_match(EE_Datetime_Field::unix_timestamp_regex, $time) ? $time : time();
338
+		$transitions = $date_time_zone->getTransitions($time);
339
+		return $first_only && ! isset($transitions['ts']) ? reset($transitions) : $transitions;
340
+	}
341
+
342
+
343
+	/**
344
+	 * Get Timezone Offset for given timezone object.
345
+	 * @param \DateTimeZone $date_time_zone
346
+	 * @param null          $time
347
+	 * @return mixed
348
+	 * @throws \DomainException
349
+	 */
350
+	public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
351
+	{
352
+		$transitions = self::get_timezone_transitions($date_time_zone, $time);
353
+		if (! isset($transitions['offset'])) {
354
+			throw new DomainException();
355
+		}
356
+		return $transitions['offset'];
357
+	}
358
+
359
+
360
+	/**
361
+	 * @access public
362
+	 * @param string $timezone_string
363
+	 */
364
+	public static function timezone_select_input($timezone_string = '')
365
+	{
366
+		// get WP date time format
367
+		$datetime_format = get_option('date_format') . ' ' . get_option('time_format');
368
+		// if passed a value, then use that, else get WP option
369
+		$timezone_string = ! empty($timezone_string) ? $timezone_string : get_option('timezone_string');
370
+		// check if the timezone is valid but don't throw any errors if it isn't
371
+		$timezone_string = EEH_DTT_Helper::validate_timezone($timezone_string, false);
372
+		$gmt_offset      = get_option('gmt_offset');
373
+
374
+		$check_zone_info = true;
375
+		if (empty($timezone_string)) {
376
+			// Create a UTC+- zone if no timezone string exists
377
+			$check_zone_info = false;
378
+			if ($gmt_offset > 0) {
379
+				$timezone_string = 'UTC+' . $gmt_offset;
380
+			} elseif ($gmt_offset < 0) {
381
+				$timezone_string = 'UTC' . $gmt_offset;
382
+			} else {
383
+				$timezone_string = 'UTC';
384
+			}
385
+		}
386
+		?>
387 387
 
388 388
         <p>
389 389
             <label for="timezone_string"><?php _e('timezone'); ?></label>
@@ -396,13 +396,13 @@  discard block
 block discarded – undo
396 396
 
397 397
         <p>
398 398
         <span><?php
399
-            printf(
400
-                __('%1$sUTC%2$s time is %3$s'),
401
-                '<abbr title="Coordinated Universal Time">',
402
-                '</abbr>',
403
-                '<code>' . date_i18n($datetime_format, false, true) . '</code>'
404
-            );
405
-            ?></span>
399
+			printf(
400
+				__('%1$sUTC%2$s time is %3$s'),
401
+				'<abbr title="Coordinated Universal Time">',
402
+				'</abbr>',
403
+				'<code>' . date_i18n($datetime_format, false, true) . '</code>'
404
+			);
405
+			?></span>
406 406
         <?php if (! empty($timezone_string) || ! empty($gmt_offset)) : ?>
407 407
         <br/><span><?php printf(__('Local time is %1$s'), '<code>' . date_i18n($datetime_format) . '</code>'); ?></span>
408 408
     <?php endif; ?>
@@ -411,693 +411,693 @@  discard block
 block discarded – undo
411 411
         <br/>
412 412
         <span>
413 413
 					<?php
414
-                    // Set TZ so localtime works.
415
-                    date_default_timezone_set($timezone_string);
416
-                    $now = localtime(time(), true);
417
-                    if ($now['tm_isdst']) {
418
-                        _e('This timezone is currently in daylight saving time.');
419
-                    } else {
420
-                        _e('This timezone is currently in standard time.');
421
-                    }
422
-                    ?>
414
+					// Set TZ so localtime works.
415
+					date_default_timezone_set($timezone_string);
416
+					$now = localtime(time(), true);
417
+					if ($now['tm_isdst']) {
418
+						_e('This timezone is currently in daylight saving time.');
419
+					} else {
420
+						_e('This timezone is currently in standard time.');
421
+					}
422
+					?>
423 423
             <br/>
424 424
             <?php
425
-            if (function_exists('timezone_transitions_get')) {
426
-                $found                   = false;
427
-                $date_time_zone_selected = new DateTimeZone($timezone_string);
428
-                $tz_offset               = timezone_offset_get($date_time_zone_selected, date_create());
429
-                $right_now               = time();
430
-                $tr['isdst']             = false;
431
-                foreach (timezone_transitions_get($date_time_zone_selected) as $tr) {
432
-                    if ($tr['ts'] > $right_now) {
433
-                        $found = true;
434
-                        break;
435
-                    }
436
-                }
437
-
438
-                if ($found) {
439
-                    $message = $tr['isdst'] ?
440
-                        __(' Daylight saving time begins on: %s.') :
441
-                        __(' Standard time begins  on: %s.');
442
-                    // Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n().
443
-                    printf($message,
444
-                        '<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >');
445
-                } else {
446
-                    _e('This timezone does not observe daylight saving time.');
447
-                }
448
-            }
449
-            // Set back to UTC.
450
-            date_default_timezone_set('UTC');
451
-            ?>
425
+			if (function_exists('timezone_transitions_get')) {
426
+				$found                   = false;
427
+				$date_time_zone_selected = new DateTimeZone($timezone_string);
428
+				$tz_offset               = timezone_offset_get($date_time_zone_selected, date_create());
429
+				$right_now               = time();
430
+				$tr['isdst']             = false;
431
+				foreach (timezone_transitions_get($date_time_zone_selected) as $tr) {
432
+					if ($tr['ts'] > $right_now) {
433
+						$found = true;
434
+						break;
435
+					}
436
+				}
437
+
438
+				if ($found) {
439
+					$message = $tr['isdst'] ?
440
+						__(' Daylight saving time begins on: %s.') :
441
+						__(' Standard time begins  on: %s.');
442
+					// Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n().
443
+					printf($message,
444
+						'<code >' . date_i18n($datetime_format, $tr['ts'] + ($tz_offset - $tr['offset'])) . '</code >');
445
+				} else {
446
+					_e('This timezone does not observe daylight saving time.');
447
+				}
448
+			}
449
+			// Set back to UTC.
450
+			date_default_timezone_set('UTC');
451
+			?>
452 452
 				</span></p>
453 453
         <?php
454
-    endif;
455
-    }
456
-
457
-
458
-    /**
459
-     * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
460
-     * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
461
-     * the site is used.
462
-     * This is used typically when using a Unix timestamp any core WP functions that expect their specially
463
-     * computed timestamp (i.e. date_i18n() )
464
-     *
465
-     * @param int    $unix_timestamp                  if 0, then time() will be used.
466
-     * @param string $timezone_string                 timezone_string. If empty, then the current set timezone for the
467
-     *                                                site will be used.
468
-     * @return int      $unix_timestamp with the offset applied for the given timezone.
469
-     */
470
-    public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
471
-    {
472
-        $unix_timestamp  = $unix_timestamp === 0 ? time() : (int)$unix_timestamp;
473
-        $timezone_string = self::get_valid_timezone_string($timezone_string);
474
-        $TimeZone        = new DateTimeZone($timezone_string);
475
-
476
-        $DateTime = new DateTime('@' . $unix_timestamp, $TimeZone);
477
-        $offset   = timezone_offset_get($TimeZone, $DateTime);
478
-        return (int)$DateTime->format('U') + (int)$offset;
479
-    }
480
-
481
-
482
-    /**
483
-     *    _set_date_time_field
484
-     *    modifies EE_Base_Class EE_Datetime_Field objects
485
-     *
486
-     * @param  EE_Base_Class $obj                 EE_Base_Class object
487
-     * @param    DateTime    $DateTime            PHP DateTime object
488
-     * @param  string        $datetime_field_name the datetime fieldname to be manipulated
489
-     * @return    EE_Base_Class
490
-     */
491
-    protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name)
492
-    {
493
-        // grab current datetime format
494
-        $current_format = $obj->get_format();
495
-        // set new full timestamp format
496
-        $obj->set_date_format(EE_Datetime_Field::mysql_date_format);
497
-        $obj->set_time_format(EE_Datetime_Field::mysql_time_format);
498
-        // set the new date value using a full timestamp format so that no data is lost
499
-        $obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format));
500
-        // reset datetime formats
501
-        $obj->set_date_format($current_format[0]);
502
-        $obj->set_time_format($current_format[1]);
503
-        return $obj;
504
-    }
505
-
506
-
507
-    /**
508
-     *    date_time_add
509
-     *    helper for doing simple datetime calculations on a given datetime from EE_Base_Class
510
-     *    and modifying it IN the EE_Base_Class so you don't have to do anything else.
511
-     *
512
-     * @param  EE_Base_Class $obj                 EE_Base_Class object
513
-     * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
514
-     * @param  string        $period              what you are adding. The options are (years, months, days, hours,
515
-     *                                            minutes, seconds) defaults to years
516
-     * @param  integer       $value               what you want to increment the time by
517
-     * @return EE_Base_Class           return the EE_Base_Class object so right away you can do something with it
518
-     *                                 (chaining)
519
-     */
520
-    public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
521
-    {
522
-        //get the raw UTC date.
523
-        $DateTime = $obj->get_DateTime_object($datetime_field_name);
524
-        $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value);
525
-        return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
526
-    }
527
-
528
-
529
-    /**
530
-     *    date_time_subtract
531
-     *    same as date_time_add except subtracting value instead of adding.
532
-     *
533
-     * @param \EE_Base_Class $obj
534
-     * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
535
-     * @param string         $period
536
-     * @param int            $value
537
-     * @return \EE_Base_Class
538
-     */
539
-    public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
540
-    {
541
-        //get the raw UTC date
542
-        $DateTime = $obj->get_DateTime_object($datetime_field_name);
543
-        $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-');
544
-        return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
545
-    }
546
-
547
-
548
-    /**
549
-     * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters
550
-     *
551
-     * @param  DateTime $DateTime DateTime object
552
-     * @param  string   $period   a value to indicate what interval is being used in the calculation. The options are
553
-     *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
554
-     * @param  integer  $value    What you want to increment the date by
555
-     * @param  string   $operand  What operand you wish to use for the calculation
556
-     * @return \DateTime return whatever type came in.
557
-     * @throws \EE_Error
558
-     */
559
-    protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
560
-    {
561
-        if (! $DateTime instanceof DateTime) {
562
-            throw new EE_Error(
563
-                sprintf(
564
-                    __('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
565
-                    print_r($DateTime, true)
566
-                )
567
-            );
568
-        }
569
-        switch ($period) {
570
-            case 'years' :
571
-                $value = 'P' . $value . 'Y';
572
-                break;
573
-            case 'months' :
574
-                $value = 'P' . $value . 'M';
575
-                break;
576
-            case 'weeks' :
577
-                $value = 'P' . $value . 'W';
578
-                break;
579
-            case 'days' :
580
-                $value = 'P' . $value . 'D';
581
-                break;
582
-            case 'hours' :
583
-                $value = 'PT' . $value . 'H';
584
-                break;
585
-            case 'minutes' :
586
-                $value = 'PT' . $value . 'M';
587
-                break;
588
-            case 'seconds' :
589
-                $value = 'PT' . $value . 'S';
590
-                break;
591
-        }
592
-        switch ($operand) {
593
-            case '+':
594
-                $DateTime->add(new DateInterval($value));
595
-                break;
596
-            case '-':
597
-                $DateTime->sub(new DateInterval($value));
598
-                break;
599
-        }
600
-        return $DateTime;
601
-    }
602
-
603
-
604
-    /**
605
-     * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters
606
-     *
607
-     * @param  int     $timestamp Unix timestamp
608
-     * @param  string  $period    a value to indicate what interval is being used in the calculation. The options are
609
-     *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
610
-     * @param  integer $value     What you want to increment the date by
611
-     * @param  string  $operand   What operand you wish to use for the calculation
612
-     * @return \DateTime return whatever type came in.
613
-     * @throws \EE_Error
614
-     */
615
-    protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
616
-    {
617
-        if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
618
-            throw new EE_Error(
619
-                sprintf(
620
-                    __('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
621
-                    print_r($timestamp, true)
622
-                )
623
-            );
624
-        }
625
-        switch ($period) {
626
-            case 'years' :
627
-                $value = YEAR_IN_SECONDS * $value;
628
-                break;
629
-            case 'months' :
630
-                $value = YEAR_IN_SECONDS / 12 * $value;
631
-                break;
632
-            case 'weeks' :
633
-                $value = WEEK_IN_SECONDS * $value;
634
-                break;
635
-            case 'days' :
636
-                $value = DAY_IN_SECONDS * $value;
637
-                break;
638
-            case 'hours' :
639
-                $value = HOUR_IN_SECONDS * $value;
640
-                break;
641
-            case 'minutes' :
642
-                $value = MINUTE_IN_SECONDS * $value;
643
-                break;
644
-        }
645
-        switch ($operand) {
646
-            case '+':
647
-                $timestamp += $value;
648
-                break;
649
-            case '-':
650
-                $timestamp -= $value;
651
-                break;
652
-        }
653
-        return $timestamp;
654
-    }
655
-
656
-
657
-    /**
658
-     * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming
659
-     * parameters and returns the new timestamp or DateTime.
660
-     *
661
-     * @param  int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp
662
-     * @param  string         $period                a value to indicate what interval is being used in the
663
-     *                                               calculation. The options are 'years', 'months', 'days', 'hours',
664
-     *                                               'minutes', 'seconds'. Defaults to years.
665
-     * @param  integer        $value                 What you want to increment the date by
666
-     * @param  string         $operand               What operand you wish to use for the calculation
667
-     * @return mixed string|DateTime          return whatever type came in.
668
-     */
669
-    public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+')
670
-    {
671
-        if ($DateTime_or_timestamp instanceof DateTime) {
672
-            return EEH_DTT_Helper::_modify_datetime_object($DateTime_or_timestamp, $period, $value, $operand);
673
-        } else if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) {
674
-            return EEH_DTT_Helper::_modify_timestamp($DateTime_or_timestamp, $period, $value, $operand);
675
-        } else {
676
-            //error
677
-            return $DateTime_or_timestamp;
678
-        }
679
-    }
680
-
681
-
682
-    /**
683
-     * The purpose of this helper method is to receive an incoming format string in php date/time format
684
-     * and spit out the js and moment.js equivalent formats.
685
-     * Note, if no format string is given, then it is assumed the user wants what is set for WP.
686
-     * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date-
687
-     * time picker.
688
-     *
689
-     * @see http://stackoverflow.com/posts/16725290/ for the code inspiration.
690
-     * @param null $date_format_string
691
-     * @param null $time_format_string
692
-     * @return array
693
-     *                array(
694
-     *                'js' => array (
695
-     *                'date' => //date format
696
-     *                'time' => //time format
697
-     *                ),
698
-     *                'moment' => //date and time format.
699
-     *                )
700
-     */
701
-    public static function convert_php_to_js_and_moment_date_formats(
702
-        $date_format_string = null,
703
-        $time_format_string = null
704
-    ) {
705
-        if ($date_format_string === null) {
706
-            $date_format_string = get_option('date_format');
707
-        }
708
-
709
-        if ($time_format_string === null) {
710
-            $time_format_string = get_option('time_format');
711
-        }
712
-
713
-        $date_format = self::_php_to_js_moment_converter($date_format_string);
714
-        $time_format = self::_php_to_js_moment_converter($time_format_string);
715
-
716
-        return array(
717
-            'js'     => array(
718
-                'date' => $date_format['js'],
719
-                'time' => $time_format['js'],
720
-            ),
721
-            'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
722
-        );
723
-    }
724
-
725
-
726
-    /**
727
-     * This converts incoming format string into js and moment variations.
728
-     *
729
-     * @param string $format_string incoming php format string
730
-     * @return array js and moment formats.
731
-     */
732
-    protected static function _php_to_js_moment_converter($format_string)
733
-    {
734
-        /**
735
-         * This is a map of symbols for formats.
736
-         * The index is the php symbol, the equivalent values are in the array.
737
-         *
738
-         * @var array
739
-         */
740
-        $symbols_map      = array(
741
-            // Day
742
-            //01
743
-            'd' => array(
744
-                'js'     => 'dd',
745
-                'moment' => 'DD',
746
-            ),
747
-            //Mon
748
-            'D' => array(
749
-                'js'     => 'D',
750
-                'moment' => 'ddd',
751
-            ),
752
-            //1,2,...31
753
-            'j' => array(
754
-                'js'     => 'd',
755
-                'moment' => 'D',
756
-            ),
757
-            //Monday
758
-            'l' => array(
759
-                'js'     => 'DD',
760
-                'moment' => 'dddd',
761
-            ),
762
-            //ISO numeric representation of the day of the week (1-6)
763
-            'N' => array(
764
-                'js'     => '',
765
-                'moment' => 'E',
766
-            ),
767
-            //st,nd.rd
768
-            'S' => array(
769
-                'js'     => '',
770
-                'moment' => 'o',
771
-            ),
772
-            //numeric representation of day of week (0-6)
773
-            'w' => array(
774
-                'js'     => '',
775
-                'moment' => 'd',
776
-            ),
777
-            //day of year starting from 0 (0-365)
778
-            'z' => array(
779
-                'js'     => 'o',
780
-                'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1
781
-            ),
782
-            // Week
783
-            //ISO-8601 week number of year (weeks starting on monday)
784
-            'W' => array(
785
-                'js'     => '',
786
-                'moment' => 'w',
787
-            ),
788
-            // Month
789
-            // January...December
790
-            'F' => array(
791
-                'js'     => 'MM',
792
-                'moment' => 'MMMM',
793
-            ),
794
-            //01...12
795
-            'm' => array(
796
-                'js'     => 'mm',
797
-                'moment' => 'MM',
798
-            ),
799
-            //Jan...Dec
800
-            'M' => array(
801
-                'js'     => 'M',
802
-                'moment' => 'MMM',
803
-            ),
804
-            //1-12
805
-            'n' => array(
806
-                'js'     => 'm',
807
-                'moment' => 'M',
808
-            ),
809
-            //number of days in given month
810
-            't' => array(
811
-                'js'     => '',
812
-                'moment' => '',
813
-            ),
814
-            // Year
815
-            //whether leap year or not 1/0
816
-            'L' => array(
817
-                'js'     => '',
818
-                'moment' => '',
819
-            ),
820
-            //ISO-8601 year number
821
-            'o' => array(
822
-                'js'     => '',
823
-                'moment' => 'GGGG',
824
-            ),
825
-            //1999...2003
826
-            'Y' => array(
827
-                'js'     => 'yy',
828
-                'moment' => 'YYYY',
829
-            ),
830
-            //99...03
831
-            'y' => array(
832
-                'js'     => 'y',
833
-                'moment' => 'YY',
834
-            ),
835
-            // Time
836
-            // am/pm
837
-            'a' => array(
838
-                'js'     => 'tt',
839
-                'moment' => 'a',
840
-            ),
841
-            // AM/PM
842
-            'A' => array(
843
-                'js'     => 'TT',
844
-                'moment' => 'A',
845
-            ),
846
-            // Swatch Internet Time?!?
847
-            'B' => array(
848
-                'js'     => '',
849
-                'moment' => '',
850
-            ),
851
-            //1...12
852
-            'g' => array(
853
-                'js'     => 'h',
854
-                'moment' => 'h',
855
-            ),
856
-            //0...23
857
-            'G' => array(
858
-                'js'     => 'H',
859
-                'moment' => 'H',
860
-            ),
861
-            //01...12
862
-            'h' => array(
863
-                'js'     => 'hh',
864
-                'moment' => 'hh',
865
-            ),
866
-            //00...23
867
-            'H' => array(
868
-                'js'     => 'HH',
869
-                'moment' => 'HH',
870
-            ),
871
-            //00..59
872
-            'i' => array(
873
-                'js'     => 'mm',
874
-                'moment' => 'mm',
875
-            ),
876
-            //seconds... 00...59
877
-            's' => array(
878
-                'js'     => 'ss',
879
-                'moment' => 'ss',
880
-            ),
881
-            //microseconds
882
-            'u' => array(
883
-                'js'     => '',
884
-                'moment' => '',
885
-            ),
886
-        );
887
-        $jquery_ui_format = "";
888
-        $moment_format    = "";
889
-        $escaping         = false;
890
-        for ($i = 0; $i < strlen($format_string); $i++) {
891
-            $char = $format_string[$i];
892
-            if ($char === '\\') { // PHP date format escaping character
893
-                $i++;
894
-                if ($escaping) {
895
-                    $jquery_ui_format .= $format_string[$i];
896
-                    $moment_format .= $format_string[$i];
897
-                } else {
898
-                    $jquery_ui_format .= '\'' . $format_string[$i];
899
-                    $moment_format .= $format_string[$i];
900
-                }
901
-                $escaping = true;
902
-            } else {
903
-                if ($escaping) {
904
-                    $jquery_ui_format .= "'";
905
-                    $moment_format .= "'";
906
-                    $escaping = false;
907
-                }
908
-                if (isset($symbols_map[$char])) {
909
-                    $jquery_ui_format .= $symbols_map[$char]['js'];
910
-                    $moment_format .= $symbols_map[$char]['moment'];
911
-                } else {
912
-                    $jquery_ui_format .= $char;
913
-                    $moment_format .= $char;
914
-                }
915
-            }
916
-        }
917
-        return array('js' => $jquery_ui_format, 'moment' => $moment_format);
918
-    }
919
-
920
-
921
-    /**
922
-     * This takes an incoming format string and validates it to ensure it will work fine with PHP.
923
-     *
924
-     * @param string $format_string   Incoming format string for php date().
925
-     * @return mixed bool|array  If all is okay then TRUE is returned.  Otherwise an array of validation
926
-     *                                errors is returned.  So for client code calling, check for is_array() to
927
-     *                                indicate failed validations.
928
-     */
929
-    public static function validate_format_string($format_string)
930
-    {
931
-        $error_msg = array();
932
-        //time format checks
933
-        switch (true) {
934
-            case   strpos($format_string, 'h') !== false  :
935
-            case   strpos($format_string, 'g') !== false :
936
-                /**
937
-                 * if the time string has a lowercase 'h' which == 12 hour time format and there
938
-                 * is not any ante meridiem format ('a' or 'A').  Then throw an error because its
939
-                 * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am.
940
-                 */
941
-                if (strpos(strtoupper($format_string), 'A') === false) {
942
-                    $error_msg[] = __('There is a  time format for 12 hour time but no  "a" or "A" to indicate am/pm.  Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".',
943
-                        'event_espresso');
944
-                }
945
-                break;
946
-
947
-        }
948
-
949
-        return empty($error_msg) ? true : $error_msg;
950
-    }
951
-
952
-
953
-    /**
954
-     *     If the the first date starts at midnight on one day, and the next date ends at midnight on the
955
-     *     very next day then this method will return true.
956
-     *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true.
957
-     *    If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false.
958
-     *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true.
959
-     *
960
-     * @param mixed $date_1
961
-     * @param mixed $date_2
962
-     * @return bool
963
-     */
964
-    public static function dates_represent_one_24_hour_date($date_1, $date_2)
965
-    {
966
-
967
-        if (
968
-            (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) ||
969
-            ($date_1->format(EE_Datetime_Field::mysql_time_format) != '00:00:00' || $date_2->format(EE_Datetime_Field::mysql_time_format) != '00:00:00')
970
-        ) {
971
-            return false;
972
-        }
973
-        return $date_2->format('U') - $date_1->format('U') == 86400 ? true : false;
974
-    }
975
-
976
-
977
-    /**
978
-     * This returns the appropriate query interval string that can be used in sql queries involving mysql Date
979
-     * Functions.
980
-     *
981
-     * @param string $timezone_string    A timezone string in a valid format to instantiate a DateTimeZone object.
982
-     * @param string $field_for_interval The Database field that is the interval is applied to in the query.
983
-     * @return string
984
-     */
985
-    public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval)
986
-    {
987
-        try {
988
-            /** need to account for timezone offset on the selects */
989
-            $DateTimeZone = new DateTimeZone($timezone_string);
990
-        } catch (Exception $e) {
991
-            $DateTimeZone = null;
992
-        }
993
-
994
-        /**
995
-         * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds.
996
-         * Hence we do the calc for DateTimeZone::getOffset.
997
-         */
998
-        $offset         = $DateTimeZone instanceof DateTimeZone ? ($DateTimeZone->getOffset(new DateTime('now'))) / HOUR_IN_SECONDS : get_option('gmt_offset');
999
-        $query_interval = $offset < 0
1000
-            ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
1001
-            : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
1002
-        return $query_interval;
1003
-    }
1004
-
1005
-    /**
1006
-     * Retrieves the site's default timezone and returns it formatted so it's ready for display
1007
-     * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string'
1008
-     * and 'gmt_offset' WordPress options directly; or use the filter
1009
-     * FHEE__EEH_DTT_Helper__get_timezone_string_for_display
1010
-     * (although note that we remove any HTML that may be added)
1011
-     *
1012
-     * @return string
1013
-     */
1014
-    public static function get_timezone_string_for_display()
1015
-    {
1016
-        $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
1017
-        if (! empty($pretty_timezone)) {
1018
-            return esc_html($pretty_timezone);
1019
-        }
1020
-        $timezone_string = get_option('timezone_string');
1021
-        if ($timezone_string) {
1022
-            static $mo_loaded = false;
1023
-            // Load translations for continents and cities just like wp_timezone_choice does
1024
-            if (! $mo_loaded) {
1025
-                $locale = get_locale();
1026
-                $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
1027
-                load_textdomain('continents-cities', $mofile);
1028
-                $mo_loaded = true;
1029
-            }
1030
-            //well that was easy.
1031
-            $parts = explode('/', $timezone_string);
1032
-            //remove the continent
1033
-            unset($parts[0]);
1034
-            $t_parts = array();
1035
-            foreach ($parts as $part) {
1036
-                $t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities');
1037
-            }
1038
-            return implode(' - ', $t_parts);
1039
-        }
1040
-        //they haven't set the timezone string, so let's return a string like "UTC+1"
1041
-        $gmt_offset = get_option('gmt_offset');
1042
-        if (intval($gmt_offset) >= 0) {
1043
-            $prefix = '+';
1044
-        } else {
1045
-            $prefix = '';
1046
-        }
1047
-        $parts = explode('.', (string)$gmt_offset);
1048
-        if (count($parts) === 1) {
1049
-            $parts[1] = '00';
1050
-        } else {
1051
-            //convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
1052
-            //to minutes, eg 30 or 15, respectively
1053
-            $hour_fraction = (float)('0.' . $parts[1]);
1054
-            $parts[1]      = (string)$hour_fraction * 60;
1055
-        }
1056
-        return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
1057
-    }
1058
-
1059
-
1060
-
1061
-    /**
1062
-     * So PHP does this awesome thing where if you are trying to get a timestamp
1063
-     * for a month using a string like "February" or "February 2017",
1064
-     * and you don't specify a day as part of your string,
1065
-     * then PHP will use whatever the current day of the month is.
1066
-     * IF the current day of the month happens to be the 30th or 31st,
1067
-     * then PHP gets really confused by a date like February 30,
1068
-     * so instead of saying
1069
-     *      "Hey February only has 28 days (this year)...
1070
-     *      ...you must have meant the last day of the month!"
1071
-     * PHP does the next most logical thing, and bumps the date up to March 2nd,
1072
-     * because someone requesting February 30th obviously meant March 1st!
1073
-     * The way around this is to always set the day to the first,
1074
-     * so that the month will stay on the month you wanted.
1075
-     * this method will add that "1" into your date regardless of the format.
1076
-     *
1077
-     * @param string $month
1078
-     * @return string
1079
-     */
1080
-    public static function first_of_month_timestamp($month = '')
1081
-    {
1082
-        $month = (string)$month;
1083
-        $year = '';
1084
-        // check if the incoming string has a year in it or not
1085
-       if (preg_match('/\b\d{4}\b/', $month, $matches)) {
1086
-           $year = $matches[0];
1087
-           // ten remove that from the month string as well as any spaces
1088
-           $month = trim(str_replace($year, '', $month));
1089
-           // add a space before the year
1090
-           $year = " {$year}";
1091
-        }
1092
-        // return timestamp for something like "February 1 2017"
1093
-        return strtotime("{$month} 1{$year}");
1094
-    }
454
+	endif;
455
+	}
456
+
457
+
458
+	/**
459
+	 * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
460
+	 * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
461
+	 * the site is used.
462
+	 * This is used typically when using a Unix timestamp any core WP functions that expect their specially
463
+	 * computed timestamp (i.e. date_i18n() )
464
+	 *
465
+	 * @param int    $unix_timestamp                  if 0, then time() will be used.
466
+	 * @param string $timezone_string                 timezone_string. If empty, then the current set timezone for the
467
+	 *                                                site will be used.
468
+	 * @return int      $unix_timestamp with the offset applied for the given timezone.
469
+	 */
470
+	public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
471
+	{
472
+		$unix_timestamp  = $unix_timestamp === 0 ? time() : (int)$unix_timestamp;
473
+		$timezone_string = self::get_valid_timezone_string($timezone_string);
474
+		$TimeZone        = new DateTimeZone($timezone_string);
475
+
476
+		$DateTime = new DateTime('@' . $unix_timestamp, $TimeZone);
477
+		$offset   = timezone_offset_get($TimeZone, $DateTime);
478
+		return (int)$DateTime->format('U') + (int)$offset;
479
+	}
480
+
481
+
482
+	/**
483
+	 *    _set_date_time_field
484
+	 *    modifies EE_Base_Class EE_Datetime_Field objects
485
+	 *
486
+	 * @param  EE_Base_Class $obj                 EE_Base_Class object
487
+	 * @param    DateTime    $DateTime            PHP DateTime object
488
+	 * @param  string        $datetime_field_name the datetime fieldname to be manipulated
489
+	 * @return    EE_Base_Class
490
+	 */
491
+	protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name)
492
+	{
493
+		// grab current datetime format
494
+		$current_format = $obj->get_format();
495
+		// set new full timestamp format
496
+		$obj->set_date_format(EE_Datetime_Field::mysql_date_format);
497
+		$obj->set_time_format(EE_Datetime_Field::mysql_time_format);
498
+		// set the new date value using a full timestamp format so that no data is lost
499
+		$obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format));
500
+		// reset datetime formats
501
+		$obj->set_date_format($current_format[0]);
502
+		$obj->set_time_format($current_format[1]);
503
+		return $obj;
504
+	}
505
+
506
+
507
+	/**
508
+	 *    date_time_add
509
+	 *    helper for doing simple datetime calculations on a given datetime from EE_Base_Class
510
+	 *    and modifying it IN the EE_Base_Class so you don't have to do anything else.
511
+	 *
512
+	 * @param  EE_Base_Class $obj                 EE_Base_Class object
513
+	 * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
514
+	 * @param  string        $period              what you are adding. The options are (years, months, days, hours,
515
+	 *                                            minutes, seconds) defaults to years
516
+	 * @param  integer       $value               what you want to increment the time by
517
+	 * @return EE_Base_Class           return the EE_Base_Class object so right away you can do something with it
518
+	 *                                 (chaining)
519
+	 */
520
+	public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
521
+	{
522
+		//get the raw UTC date.
523
+		$DateTime = $obj->get_DateTime_object($datetime_field_name);
524
+		$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value);
525
+		return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
526
+	}
527
+
528
+
529
+	/**
530
+	 *    date_time_subtract
531
+	 *    same as date_time_add except subtracting value instead of adding.
532
+	 *
533
+	 * @param \EE_Base_Class $obj
534
+	 * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
535
+	 * @param string         $period
536
+	 * @param int            $value
537
+	 * @return \EE_Base_Class
538
+	 */
539
+	public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
540
+	{
541
+		//get the raw UTC date
542
+		$DateTime = $obj->get_DateTime_object($datetime_field_name);
543
+		$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-');
544
+		return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
545
+	}
546
+
547
+
548
+	/**
549
+	 * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters
550
+	 *
551
+	 * @param  DateTime $DateTime DateTime object
552
+	 * @param  string   $period   a value to indicate what interval is being used in the calculation. The options are
553
+	 *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
554
+	 * @param  integer  $value    What you want to increment the date by
555
+	 * @param  string   $operand  What operand you wish to use for the calculation
556
+	 * @return \DateTime return whatever type came in.
557
+	 * @throws \EE_Error
558
+	 */
559
+	protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
560
+	{
561
+		if (! $DateTime instanceof DateTime) {
562
+			throw new EE_Error(
563
+				sprintf(
564
+					__('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
565
+					print_r($DateTime, true)
566
+				)
567
+			);
568
+		}
569
+		switch ($period) {
570
+			case 'years' :
571
+				$value = 'P' . $value . 'Y';
572
+				break;
573
+			case 'months' :
574
+				$value = 'P' . $value . 'M';
575
+				break;
576
+			case 'weeks' :
577
+				$value = 'P' . $value . 'W';
578
+				break;
579
+			case 'days' :
580
+				$value = 'P' . $value . 'D';
581
+				break;
582
+			case 'hours' :
583
+				$value = 'PT' . $value . 'H';
584
+				break;
585
+			case 'minutes' :
586
+				$value = 'PT' . $value . 'M';
587
+				break;
588
+			case 'seconds' :
589
+				$value = 'PT' . $value . 'S';
590
+				break;
591
+		}
592
+		switch ($operand) {
593
+			case '+':
594
+				$DateTime->add(new DateInterval($value));
595
+				break;
596
+			case '-':
597
+				$DateTime->sub(new DateInterval($value));
598
+				break;
599
+		}
600
+		return $DateTime;
601
+	}
602
+
603
+
604
+	/**
605
+	 * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters
606
+	 *
607
+	 * @param  int     $timestamp Unix timestamp
608
+	 * @param  string  $period    a value to indicate what interval is being used in the calculation. The options are
609
+	 *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
610
+	 * @param  integer $value     What you want to increment the date by
611
+	 * @param  string  $operand   What operand you wish to use for the calculation
612
+	 * @return \DateTime return whatever type came in.
613
+	 * @throws \EE_Error
614
+	 */
615
+	protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
616
+	{
617
+		if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
618
+			throw new EE_Error(
619
+				sprintf(
620
+					__('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
621
+					print_r($timestamp, true)
622
+				)
623
+			);
624
+		}
625
+		switch ($period) {
626
+			case 'years' :
627
+				$value = YEAR_IN_SECONDS * $value;
628
+				break;
629
+			case 'months' :
630
+				$value = YEAR_IN_SECONDS / 12 * $value;
631
+				break;
632
+			case 'weeks' :
633
+				$value = WEEK_IN_SECONDS * $value;
634
+				break;
635
+			case 'days' :
636
+				$value = DAY_IN_SECONDS * $value;
637
+				break;
638
+			case 'hours' :
639
+				$value = HOUR_IN_SECONDS * $value;
640
+				break;
641
+			case 'minutes' :
642
+				$value = MINUTE_IN_SECONDS * $value;
643
+				break;
644
+		}
645
+		switch ($operand) {
646
+			case '+':
647
+				$timestamp += $value;
648
+				break;
649
+			case '-':
650
+				$timestamp -= $value;
651
+				break;
652
+		}
653
+		return $timestamp;
654
+	}
655
+
656
+
657
+	/**
658
+	 * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming
659
+	 * parameters and returns the new timestamp or DateTime.
660
+	 *
661
+	 * @param  int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp
662
+	 * @param  string         $period                a value to indicate what interval is being used in the
663
+	 *                                               calculation. The options are 'years', 'months', 'days', 'hours',
664
+	 *                                               'minutes', 'seconds'. Defaults to years.
665
+	 * @param  integer        $value                 What you want to increment the date by
666
+	 * @param  string         $operand               What operand you wish to use for the calculation
667
+	 * @return mixed string|DateTime          return whatever type came in.
668
+	 */
669
+	public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+')
670
+	{
671
+		if ($DateTime_or_timestamp instanceof DateTime) {
672
+			return EEH_DTT_Helper::_modify_datetime_object($DateTime_or_timestamp, $period, $value, $operand);
673
+		} else if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) {
674
+			return EEH_DTT_Helper::_modify_timestamp($DateTime_or_timestamp, $period, $value, $operand);
675
+		} else {
676
+			//error
677
+			return $DateTime_or_timestamp;
678
+		}
679
+	}
680
+
681
+
682
+	/**
683
+	 * The purpose of this helper method is to receive an incoming format string in php date/time format
684
+	 * and spit out the js and moment.js equivalent formats.
685
+	 * Note, if no format string is given, then it is assumed the user wants what is set for WP.
686
+	 * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date-
687
+	 * time picker.
688
+	 *
689
+	 * @see http://stackoverflow.com/posts/16725290/ for the code inspiration.
690
+	 * @param null $date_format_string
691
+	 * @param null $time_format_string
692
+	 * @return array
693
+	 *                array(
694
+	 *                'js' => array (
695
+	 *                'date' => //date format
696
+	 *                'time' => //time format
697
+	 *                ),
698
+	 *                'moment' => //date and time format.
699
+	 *                )
700
+	 */
701
+	public static function convert_php_to_js_and_moment_date_formats(
702
+		$date_format_string = null,
703
+		$time_format_string = null
704
+	) {
705
+		if ($date_format_string === null) {
706
+			$date_format_string = get_option('date_format');
707
+		}
708
+
709
+		if ($time_format_string === null) {
710
+			$time_format_string = get_option('time_format');
711
+		}
712
+
713
+		$date_format = self::_php_to_js_moment_converter($date_format_string);
714
+		$time_format = self::_php_to_js_moment_converter($time_format_string);
715
+
716
+		return array(
717
+			'js'     => array(
718
+				'date' => $date_format['js'],
719
+				'time' => $time_format['js'],
720
+			),
721
+			'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
722
+		);
723
+	}
724
+
725
+
726
+	/**
727
+	 * This converts incoming format string into js and moment variations.
728
+	 *
729
+	 * @param string $format_string incoming php format string
730
+	 * @return array js and moment formats.
731
+	 */
732
+	protected static function _php_to_js_moment_converter($format_string)
733
+	{
734
+		/**
735
+		 * This is a map of symbols for formats.
736
+		 * The index is the php symbol, the equivalent values are in the array.
737
+		 *
738
+		 * @var array
739
+		 */
740
+		$symbols_map      = array(
741
+			// Day
742
+			//01
743
+			'd' => array(
744
+				'js'     => 'dd',
745
+				'moment' => 'DD',
746
+			),
747
+			//Mon
748
+			'D' => array(
749
+				'js'     => 'D',
750
+				'moment' => 'ddd',
751
+			),
752
+			//1,2,...31
753
+			'j' => array(
754
+				'js'     => 'd',
755
+				'moment' => 'D',
756
+			),
757
+			//Monday
758
+			'l' => array(
759
+				'js'     => 'DD',
760
+				'moment' => 'dddd',
761
+			),
762
+			//ISO numeric representation of the day of the week (1-6)
763
+			'N' => array(
764
+				'js'     => '',
765
+				'moment' => 'E',
766
+			),
767
+			//st,nd.rd
768
+			'S' => array(
769
+				'js'     => '',
770
+				'moment' => 'o',
771
+			),
772
+			//numeric representation of day of week (0-6)
773
+			'w' => array(
774
+				'js'     => '',
775
+				'moment' => 'd',
776
+			),
777
+			//day of year starting from 0 (0-365)
778
+			'z' => array(
779
+				'js'     => 'o',
780
+				'moment' => 'DDD' //note moment does not start with 0 so will need to modify by subtracting 1
781
+			),
782
+			// Week
783
+			//ISO-8601 week number of year (weeks starting on monday)
784
+			'W' => array(
785
+				'js'     => '',
786
+				'moment' => 'w',
787
+			),
788
+			// Month
789
+			// January...December
790
+			'F' => array(
791
+				'js'     => 'MM',
792
+				'moment' => 'MMMM',
793
+			),
794
+			//01...12
795
+			'm' => array(
796
+				'js'     => 'mm',
797
+				'moment' => 'MM',
798
+			),
799
+			//Jan...Dec
800
+			'M' => array(
801
+				'js'     => 'M',
802
+				'moment' => 'MMM',
803
+			),
804
+			//1-12
805
+			'n' => array(
806
+				'js'     => 'm',
807
+				'moment' => 'M',
808
+			),
809
+			//number of days in given month
810
+			't' => array(
811
+				'js'     => '',
812
+				'moment' => '',
813
+			),
814
+			// Year
815
+			//whether leap year or not 1/0
816
+			'L' => array(
817
+				'js'     => '',
818
+				'moment' => '',
819
+			),
820
+			//ISO-8601 year number
821
+			'o' => array(
822
+				'js'     => '',
823
+				'moment' => 'GGGG',
824
+			),
825
+			//1999...2003
826
+			'Y' => array(
827
+				'js'     => 'yy',
828
+				'moment' => 'YYYY',
829
+			),
830
+			//99...03
831
+			'y' => array(
832
+				'js'     => 'y',
833
+				'moment' => 'YY',
834
+			),
835
+			// Time
836
+			// am/pm
837
+			'a' => array(
838
+				'js'     => 'tt',
839
+				'moment' => 'a',
840
+			),
841
+			// AM/PM
842
+			'A' => array(
843
+				'js'     => 'TT',
844
+				'moment' => 'A',
845
+			),
846
+			// Swatch Internet Time?!?
847
+			'B' => array(
848
+				'js'     => '',
849
+				'moment' => '',
850
+			),
851
+			//1...12
852
+			'g' => array(
853
+				'js'     => 'h',
854
+				'moment' => 'h',
855
+			),
856
+			//0...23
857
+			'G' => array(
858
+				'js'     => 'H',
859
+				'moment' => 'H',
860
+			),
861
+			//01...12
862
+			'h' => array(
863
+				'js'     => 'hh',
864
+				'moment' => 'hh',
865
+			),
866
+			//00...23
867
+			'H' => array(
868
+				'js'     => 'HH',
869
+				'moment' => 'HH',
870
+			),
871
+			//00..59
872
+			'i' => array(
873
+				'js'     => 'mm',
874
+				'moment' => 'mm',
875
+			),
876
+			//seconds... 00...59
877
+			's' => array(
878
+				'js'     => 'ss',
879
+				'moment' => 'ss',
880
+			),
881
+			//microseconds
882
+			'u' => array(
883
+				'js'     => '',
884
+				'moment' => '',
885
+			),
886
+		);
887
+		$jquery_ui_format = "";
888
+		$moment_format    = "";
889
+		$escaping         = false;
890
+		for ($i = 0; $i < strlen($format_string); $i++) {
891
+			$char = $format_string[$i];
892
+			if ($char === '\\') { // PHP date format escaping character
893
+				$i++;
894
+				if ($escaping) {
895
+					$jquery_ui_format .= $format_string[$i];
896
+					$moment_format .= $format_string[$i];
897
+				} else {
898
+					$jquery_ui_format .= '\'' . $format_string[$i];
899
+					$moment_format .= $format_string[$i];
900
+				}
901
+				$escaping = true;
902
+			} else {
903
+				if ($escaping) {
904
+					$jquery_ui_format .= "'";
905
+					$moment_format .= "'";
906
+					$escaping = false;
907
+				}
908
+				if (isset($symbols_map[$char])) {
909
+					$jquery_ui_format .= $symbols_map[$char]['js'];
910
+					$moment_format .= $symbols_map[$char]['moment'];
911
+				} else {
912
+					$jquery_ui_format .= $char;
913
+					$moment_format .= $char;
914
+				}
915
+			}
916
+		}
917
+		return array('js' => $jquery_ui_format, 'moment' => $moment_format);
918
+	}
919
+
920
+
921
+	/**
922
+	 * This takes an incoming format string and validates it to ensure it will work fine with PHP.
923
+	 *
924
+	 * @param string $format_string   Incoming format string for php date().
925
+	 * @return mixed bool|array  If all is okay then TRUE is returned.  Otherwise an array of validation
926
+	 *                                errors is returned.  So for client code calling, check for is_array() to
927
+	 *                                indicate failed validations.
928
+	 */
929
+	public static function validate_format_string($format_string)
930
+	{
931
+		$error_msg = array();
932
+		//time format checks
933
+		switch (true) {
934
+			case   strpos($format_string, 'h') !== false  :
935
+			case   strpos($format_string, 'g') !== false :
936
+				/**
937
+				 * if the time string has a lowercase 'h' which == 12 hour time format and there
938
+				 * is not any ante meridiem format ('a' or 'A').  Then throw an error because its
939
+				 * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am.
940
+				 */
941
+				if (strpos(strtoupper($format_string), 'A') === false) {
942
+					$error_msg[] = __('There is a  time format for 12 hour time but no  "a" or "A" to indicate am/pm.  Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".',
943
+						'event_espresso');
944
+				}
945
+				break;
946
+
947
+		}
948
+
949
+		return empty($error_msg) ? true : $error_msg;
950
+	}
951
+
952
+
953
+	/**
954
+	 *     If the the first date starts at midnight on one day, and the next date ends at midnight on the
955
+	 *     very next day then this method will return true.
956
+	 *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true.
957
+	 *    If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false.
958
+	 *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true.
959
+	 *
960
+	 * @param mixed $date_1
961
+	 * @param mixed $date_2
962
+	 * @return bool
963
+	 */
964
+	public static function dates_represent_one_24_hour_date($date_1, $date_2)
965
+	{
966
+
967
+		if (
968
+			(! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime) ||
969
+			($date_1->format(EE_Datetime_Field::mysql_time_format) != '00:00:00' || $date_2->format(EE_Datetime_Field::mysql_time_format) != '00:00:00')
970
+		) {
971
+			return false;
972
+		}
973
+		return $date_2->format('U') - $date_1->format('U') == 86400 ? true : false;
974
+	}
975
+
976
+
977
+	/**
978
+	 * This returns the appropriate query interval string that can be used in sql queries involving mysql Date
979
+	 * Functions.
980
+	 *
981
+	 * @param string $timezone_string    A timezone string in a valid format to instantiate a DateTimeZone object.
982
+	 * @param string $field_for_interval The Database field that is the interval is applied to in the query.
983
+	 * @return string
984
+	 */
985
+	public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval)
986
+	{
987
+		try {
988
+			/** need to account for timezone offset on the selects */
989
+			$DateTimeZone = new DateTimeZone($timezone_string);
990
+		} catch (Exception $e) {
991
+			$DateTimeZone = null;
992
+		}
993
+
994
+		/**
995
+		 * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds.
996
+		 * Hence we do the calc for DateTimeZone::getOffset.
997
+		 */
998
+		$offset         = $DateTimeZone instanceof DateTimeZone ? ($DateTimeZone->getOffset(new DateTime('now'))) / HOUR_IN_SECONDS : get_option('gmt_offset');
999
+		$query_interval = $offset < 0
1000
+			? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
1001
+			: 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
1002
+		return $query_interval;
1003
+	}
1004
+
1005
+	/**
1006
+	 * Retrieves the site's default timezone and returns it formatted so it's ready for display
1007
+	 * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string'
1008
+	 * and 'gmt_offset' WordPress options directly; or use the filter
1009
+	 * FHEE__EEH_DTT_Helper__get_timezone_string_for_display
1010
+	 * (although note that we remove any HTML that may be added)
1011
+	 *
1012
+	 * @return string
1013
+	 */
1014
+	public static function get_timezone_string_for_display()
1015
+	{
1016
+		$pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
1017
+		if (! empty($pretty_timezone)) {
1018
+			return esc_html($pretty_timezone);
1019
+		}
1020
+		$timezone_string = get_option('timezone_string');
1021
+		if ($timezone_string) {
1022
+			static $mo_loaded = false;
1023
+			// Load translations for continents and cities just like wp_timezone_choice does
1024
+			if (! $mo_loaded) {
1025
+				$locale = get_locale();
1026
+				$mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
1027
+				load_textdomain('continents-cities', $mofile);
1028
+				$mo_loaded = true;
1029
+			}
1030
+			//well that was easy.
1031
+			$parts = explode('/', $timezone_string);
1032
+			//remove the continent
1033
+			unset($parts[0]);
1034
+			$t_parts = array();
1035
+			foreach ($parts as $part) {
1036
+				$t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities');
1037
+			}
1038
+			return implode(' - ', $t_parts);
1039
+		}
1040
+		//they haven't set the timezone string, so let's return a string like "UTC+1"
1041
+		$gmt_offset = get_option('gmt_offset');
1042
+		if (intval($gmt_offset) >= 0) {
1043
+			$prefix = '+';
1044
+		} else {
1045
+			$prefix = '';
1046
+		}
1047
+		$parts = explode('.', (string)$gmt_offset);
1048
+		if (count($parts) === 1) {
1049
+			$parts[1] = '00';
1050
+		} else {
1051
+			//convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
1052
+			//to minutes, eg 30 or 15, respectively
1053
+			$hour_fraction = (float)('0.' . $parts[1]);
1054
+			$parts[1]      = (string)$hour_fraction * 60;
1055
+		}
1056
+		return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
1057
+	}
1058
+
1059
+
1060
+
1061
+	/**
1062
+	 * So PHP does this awesome thing where if you are trying to get a timestamp
1063
+	 * for a month using a string like "February" or "February 2017",
1064
+	 * and you don't specify a day as part of your string,
1065
+	 * then PHP will use whatever the current day of the month is.
1066
+	 * IF the current day of the month happens to be the 30th or 31st,
1067
+	 * then PHP gets really confused by a date like February 30,
1068
+	 * so instead of saying
1069
+	 *      "Hey February only has 28 days (this year)...
1070
+	 *      ...you must have meant the last day of the month!"
1071
+	 * PHP does the next most logical thing, and bumps the date up to March 2nd,
1072
+	 * because someone requesting February 30th obviously meant March 1st!
1073
+	 * The way around this is to always set the day to the first,
1074
+	 * so that the month will stay on the month you wanted.
1075
+	 * this method will add that "1" into your date regardless of the format.
1076
+	 *
1077
+	 * @param string $month
1078
+	 * @return string
1079
+	 */
1080
+	public static function first_of_month_timestamp($month = '')
1081
+	{
1082
+		$month = (string)$month;
1083
+		$year = '';
1084
+		// check if the incoming string has a year in it or not
1085
+	   if (preg_match('/\b\d{4}\b/', $month, $matches)) {
1086
+		   $year = $matches[0];
1087
+		   // ten remove that from the month string as well as any spaces
1088
+		   $month = trim(str_replace($year, '', $month));
1089
+		   // add a space before the year
1090
+		   $year = " {$year}";
1091
+		}
1092
+		// return timestamp for something like "February 1 2017"
1093
+		return strtotime("{$month} 1{$year}");
1094
+	}
1095 1095
 
1096 1096
 	/**
1097
-     * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone.  So it may be midnight
1098
-	* for this sites timezone, but the timestamp could be some other time GMT.
1099
-    */
1100
-    public static function tomorrow()
1097
+	 * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone.  So it may be midnight
1098
+	 * for this sites timezone, but the timestamp could be some other time GMT.
1099
+	 */
1100
+	public static function tomorrow()
1101 1101
 	{
1102 1102
 		//The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive
1103 1103
 		//before adding to the timestamp.  Why? Because we want tomorrow to be for midnight the next day in THIS timezone
Please login to merge, or discard this patch.