Completed
Branch BUG-10738-inconsistency-in-ses... (cda363)
by
unknown
13:38 queued 12s
created

EE_Datetime_Field   C

Complexity

Total Complexity 78

Size/Duplication

Total Lines 753
Duplicated Lines 4.52 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
dl 34
loc 753
rs 5
c 0
b 0
f 0
wmc 78
lcom 2
cbo 4

29 Methods

Rating   Name   Duplication   Size   Complexity  
A get_timezone_abbrev() 0 7 1
A get_default_value() 0 8 2
A getSchemaDescription() 0 7 1
B __construct() 0 21 5
A get_UTC_DateTimeZone() 0 6 2
A get_blog_DateTimeZone() 0 6 2
A prepare_for_set() 0 4 1
B _get_date_time_output() 0 18 6
A set_date_time_output() 0 4 1
A set_timezone() 0 11 4
A _create_timezone_object_from_timezone_string() 0 4 1
A get_timezone() 0 4 1
A set_date_format() 0 8 2
A get_date_format() 0 4 2
A set_time_format() 0 8 2
A get_time_format() 0 4 2
A set_pretty_date_format() 0 4 1
A set_pretty_time_format() 0 4 1
A prepare_for_set_with_new_time() 17 20 2
A prepare_for_set_with_new_date() 17 20 2
A prepare_for_get() 0 4 1
A prepare_for_pretty_echoing() 0 4 2
C _prepare_for_display() 0 50 7
C prepare_for_use_in_db() 0 30 7
B prepare_for_set_from_db() 0 32 6
A _display_timezone() 0 15 2
C _get_date_object() 0 59 10
A get_timezone_transitions() 0 4 1
A get_timezone_offset() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EE_Datetime_Field often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EE_Datetime_Field, and based on these observations, apply Extract Interface, too.

1
<?php
2
use EventEspresso\core\domain\entities\DbSafeDateTime;
3
4
defined('EVENT_ESPRESSO_VERSION') || exit;
5
6
/**
7
 * EE_Datetime_Field
8
 * Text_Fields is a base class for any fields which are have integer value. (Exception: foreign and private key fields.
9
 * Wish PHP had multiple-inheritance for this...)
10
 *
11
 * @package               Event Espresso
12
 * @subpackage            /core/db_models/fields/EE_Datetime_Field.php
13
 * @author                Darren Ethier
14
 */
15
class EE_Datetime_Field extends EE_Model_Field_Base
16
{
17
18
    /**
19
     * The pattern we're looking for is if only the characters 0-9 are found and there are only
20
     * 10 or more numbers (because 9 numbers even with all 9's would be sometime in 2001 )
21
     *
22
     * @type string unix_timestamp_regex
23
     */
24
    const unix_timestamp_regex = '/[0-9]{10,}/';
25
26
    /**
27
     * @type string mysql_timestamp_format
28
     */
29
    const mysql_timestamp_format = 'Y-m-d H:i:s';
30
31
    /**
32
     * @type string mysql_date_format
33
     */
34
    const mysql_date_format = 'Y-m-d';
35
36
    /**
37
     * @type string mysql_time_format
38
     */
39
    const mysql_time_format = 'H:i:s';
40
41
    /**
42
     * Const for using in the default value. If the field's default is set to this,
43
     * then we will return the time of calling `get_default_value()`, not
44
     * just the current time at construction
45
     */
46
    const now = 'now';
47
48
    /**
49
     * The following properties hold the default formats for date and time.
50
     * Defaults are set via the constructor and can be overridden on class instantiation.
51
     * However they can also be overridden later by the set_format() method
52
     * (and corresponding set_date_format, set_time_format methods);
53
     */
54
    /**
55
     * @type string $_date_format
56
     */
57
    protected $_date_format = '';
58
59
    /**
60
     * @type string $_time_format
61
     */
62
    protected $_time_format = '';
63
64
    /**
65
     * @type string $_pretty_date_format
66
     */
67
    protected $_pretty_date_format = '';
68
69
    /**
70
     * @type string $_pretty_time_format
71
     */
72
    protected $_pretty_time_format = '';
73
74
    /**
75
     * @type DateTimeZone $_DateTimeZone
76
     */
77
    protected $_DateTimeZone;
78
79
    /**
80
     * @type DateTimeZone $_UTC_DateTimeZone
81
     */
82
    protected $_UTC_DateTimeZone;
83
84
    /**
85
     * @type DateTimeZone $_blog_DateTimeZone
86
     */
87
    protected $_blog_DateTimeZone;
88
89
90
    /**
91
     * This property holds how we want the output returned when getting a datetime string.  It is set for the
92
     * set_date_time_output() method.  By default this is empty.  When empty, we are assuming that we want both date
93
     * and time returned via getters.
94
     *
95
     * @var mixed (null|string)
96
     */
97
    protected $_date_time_output;
98
99
100
    /**
101
     * timezone string
102
     * This gets set by the constructor and can be changed by the "set_timezone()" method so that we know what timezone
103
     * incoming strings|timestamps are in.  This can also be used before a get to set what timezone you want strings
104
     * coming out of the object to be in.  Default timezone is the current WP timezone option setting
105
     *
106
     * @var string
107
     */
108
    protected $_timezone_string;
109
110
111
    /**
112
     * This holds whatever UTC offset for the blog (we automatically convert timezone strings into their related
113
     * offsets for comparison purposes).
114
     *
115
     * @var int
116
     */
117
    protected $_blog_offset;
118
119
120
121
    /**
122
     * @param string $table_column
123
     * @param string $nice_name
124
     * @param bool   $nullable
125
     * @param string $default_value
126
     * @param string $timezone_string
127
     * @param string $date_format
128
     * @param string $time_format
129
     * @param string $pretty_date_format
130
     * @param string $pretty_time_format
131
     * @throws EE_Error
132
     * @throws InvalidArgumentException
133
     */
134
    public function __construct(
135
        $table_column,
136
        $nice_name,
137
        $nullable,
138
        $default_value,
139
        $timezone_string = '',
140
        $date_format = '',
141
        $time_format = '',
142
        $pretty_date_format = '',
143
        $pretty_time_format = ''
144
    ) {
145
146
        $this->_date_format        = ! empty($date_format) ? $date_format : get_option('date_format');
147
        $this->_time_format        = ! empty($time_format) ? $time_format : get_option('time_format');
148
        $this->_pretty_date_format = ! empty($pretty_date_format) ? $pretty_date_format : get_option('date_format');
149
        $this->_pretty_time_format = ! empty($pretty_time_format) ? $pretty_time_format : get_option('time_format');
150
151
        parent::__construct($table_column, $nice_name, $nullable, $default_value);
152
        $this->set_timezone($timezone_string);
153
        $this->setSchemaFormat('date-time');
154
    }
155
156
157
    /**
158
     * @return DateTimeZone
159
     * @throws \EE_Error
160
     */
161
    public function get_UTC_DateTimeZone()
162
    {
163
        return $this->_UTC_DateTimeZone instanceof DateTimeZone
164
            ? $this->_UTC_DateTimeZone
165
            : $this->_create_timezone_object_from_timezone_string('UTC');
166
    }
167
168
169
    /**
170
     * @return DateTimeZone
171
     * @throws \EE_Error
172
     */
173
    public function get_blog_DateTimeZone()
174
    {
175
        return $this->_blog_DateTimeZone instanceof DateTimeZone
176
            ? $this->_blog_DateTimeZone
177
            : $this->_create_timezone_object_from_timezone_string('');
178
    }
179
180
181
    /**
182
     * this prepares any incoming date data and make sure its converted to a utc unix timestamp
183
     *
184
     * @param  string|int $value_inputted_for_field_on_model_object could be a string formatted date time or int unix
185
     *                                                              timestamp
186
     * @return DateTime
187
     */
188
    public function prepare_for_set($value_inputted_for_field_on_model_object)
189
    {
190
        return $this->_get_date_object($value_inputted_for_field_on_model_object);
191
    }
192
193
194
    /**
195
     * This returns the format string to be used by getters depending on what the $_date_time_output property is set at.
196
     * getters need to know whether we're just returning the date or the time or both.  By default we return both.
197
     *
198
     * @param bool $pretty If we're returning the pretty formats or standard format string.
199
     * @return string    The final assembled format string.
200
     */
201
    protected function _get_date_time_output($pretty = false)
202
    {
203
204
        switch ($this->_date_time_output) {
205
            case 'time' :
206
                return $pretty ? $this->_pretty_time_format : $this->_time_format;
207
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
208
209
            case 'date' :
210
                return $pretty ? $this->_pretty_date_format : $this->_date_format;
211
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
212
213
            default :
214
                return $pretty
215
                    ? $this->_pretty_date_format . ' ' . $this->_pretty_time_format
216
                    : $this->_date_format . ' ' . $this->_time_format;
217
        }
218
    }
219
220
221
    /**
222
     * This just sets the $_date_time_output property so we can flag how date and times are formatted before being
223
     * returned (using the format properties)
224
     *
225
     * @param string $what acceptable values are 'time' or 'date'.
226
     *                     Any other value will be set but will always result
227
     *                     in both 'date' and 'time' being returned.
228
     * @return void
229
     */
230
    public function set_date_time_output($what = null)
231
    {
232
        $this->_date_time_output = $what;
233
    }
234
235
236
    /**
237
     * See $_timezone property for description of what the timezone property is for.  This SETS the timezone internally
238
     * for being able to reference what timezone we are running conversions on when converting TO the internal timezone
239
     * (UTC Unix Timestamp) for the object OR when converting FROM the internal timezone (UTC Unix Timestamp).
240
     * We also set some other properties in this method.
241
     *
242
     * @param string $timezone_string A valid timezone string as described by @link
243
     *                                http://www.php.net/manual/en/timezones.php
244
     * @return void
245
     * @throws \EE_Error
246
     */
247
    public function set_timezone($timezone_string)
248
    {
249
        if (empty($timezone_string) && $this->_timezone_string !== null) {
250
            // leave the timezone AS-IS if we already have one and
251
            // the function arg didn't provide one
252
            return;
253
        }
254
        $timezone_string        = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
255
        $this->_timezone_string = ! empty($timezone_string) ? $timezone_string : 'UTC';
256
        $this->_DateTimeZone    = $this->_create_timezone_object_from_timezone_string($this->_timezone_string);
257
    }
258
259
260
    /**
261
     * _create_timezone_object_from_timezone_name
262
     *
263
     * @access protected
264
     * @param string $timezone_string
265
     * @return \DateTimeZone
266
     * @throws \EE_Error
267
     */
268
    protected function _create_timezone_object_from_timezone_string($timezone_string = '')
269
    {
270
        return new DateTimeZone(EEH_DTT_Helper::get_valid_timezone_string($timezone_string));
271
    }
272
273
274
    /**
275
     * This just returns whatever is set for the current timezone.
276
     *
277
     * @access public
278
     * @return string timezone string
279
     */
280
    public function get_timezone()
281
    {
282
        return $this->_timezone_string;
283
    }
284
285
286
    /**
287
     * set the $_date_format property
288
     *
289
     * @access public
290
     * @param string $format a new date format (corresponding to formats accepted by PHP date() function)
291
     * @param bool   $pretty Whether to set pretty format or not.
292
     * @return void
293
     */
294
    public function set_date_format($format, $pretty = false)
295
    {
296
        if ($pretty) {
297
            $this->_pretty_date_format = $format;
298
        } else {
299
            $this->_date_format = $format;
300
        }
301
    }
302
303
304
    /**
305
     * return the $_date_format property value.
306
     *
307
     * @param bool $pretty Whether to get pretty format or not.
308
     * @return string
309
     */
310
    public function get_date_format($pretty = false)
311
    {
312
        return $pretty ? $this->_pretty_date_format : $this->_date_format;
313
    }
314
315
316
    /**
317
     * set the $_time_format property
318
     *
319
     * @access public
320
     * @param string $format a new time format (corresponding to formats accepted by PHP date() function)
321
     * @param bool   $pretty Whether to set pretty format or not.
322
     * @return void
323
     */
324
    public function set_time_format($format, $pretty = false)
325
    {
326
        if ($pretty) {
327
            $this->_pretty_time_format = $format;
328
        } else {
329
            $this->_time_format = $format;
330
        }
331
    }
332
333
334
    /**
335
     * return the $_time_format property value.
336
     *
337
     * @param bool $pretty Whether to get pretty format or not.
338
     * @return string
339
     */
340
    public function get_time_format($pretty = false)
341
    {
342
        return $pretty ? $this->_pretty_time_format : $this->_time_format;
343
    }
344
345
346
    /**
347
     * set the $_pretty_date_format property
348
     *
349
     * @access public
350
     * @param string $format a new pretty date format (corresponding to formats accepted by PHP date() function)
351
     * @return void
352
     */
353
    public function set_pretty_date_format($format)
354
    {
355
        $this->_pretty_date_format = $format;
356
    }
357
358
359
    /**
360
     * set the $_pretty_time_format property
361
     *
362
     * @access public
363
     * @param string $format a new pretty time format (corresponding to formats accepted by PHP date() function)
364
     * @return void
365
     */
366
    public function set_pretty_time_format($format)
367
    {
368
        $this->_pretty_time_format = $format;
369
    }
370
371
372
    /**
373
     * Only sets the time portion of the datetime.
374
     *
375
     * @param string|DateTime $time_to_set_string like 8am OR a DateTime object.
376
     * @param DateTime        $current            current DateTime object for the datetime field
377
     * @return DateTime
378
     */
379 View Code Duplication
    public function prepare_for_set_with_new_time($time_to_set_string, DateTime $current)
380
    {
381
        // if $time_to_set_string is datetime object, then let's use it to set the parse array.
382
        // Otherwise parse the string.
383
        if ($time_to_set_string instanceof DateTime) {
384
            $parsed = array(
385
                'hour'   => $time_to_set_string->format('H'),
386
                'minute' => $time_to_set_string->format('i'),
387
                'second' => $time_to_set_string->format('s'),
388
            );
389
        } else {
390
            //parse incoming string
391
            $parsed = date_parse_from_format($this->_time_format, $time_to_set_string);
392
        }
393
394
        //make sure $current is in the correct timezone.
395
        $current->setTimezone($this->_DateTimeZone);
396
397
        return $current->setTime($parsed['hour'], $parsed['minute'], $parsed['second']);
398
    }
399
400
401
    /**
402
     * Only sets the date portion of the datetime.
403
     *
404
     * @param string|DateTime $date_to_set_string like Friday, January 8th or a DateTime object.
405
     * @param DateTime        $current            current DateTime object for the datetime field
406
     * @return DateTime
407
     */
408 View Code Duplication
    public function prepare_for_set_with_new_date($date_to_set_string, DateTime $current)
409
    {
410
        // if $time_to_set_string is datetime object, then let's use it to set the parse array.
411
        // Otherwise parse the string.
412
        if ($date_to_set_string instanceof DateTime) {
413
            $parsed = array(
414
                'year'  => $date_to_set_string->format('Y'),
415
                'month' => $date_to_set_string->format('m'),
416
                'day'   => $date_to_set_string->format('d'),
417
            );
418
        } else {
419
            //parse incoming string
420
            $parsed = date_parse_from_format($this->_date_format, $date_to_set_string);
421
        }
422
423
        //make sure $current is in the correct timezone
424
        $current->setTimezone($this->_DateTimeZone);
425
426
        return $current->setDate($parsed['year'], $parsed['month'], $parsed['day']);
427
    }
428
429
430
    /**
431
     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0 timezone).  When the
432
     * datetime gets to this stage it should ALREADY be in UTC time
433
     *
434
     * @param  DateTime $DateTime
435
     * @return string formatted date time for given timezone
436
     * @throws \EE_Error
437
     */
438
    public function prepare_for_get($DateTime)
439
    {
440
        return $this->_prepare_for_display($DateTime);
441
    }
442
443
444
    /**
445
     * This differs from prepare_for_get in that it considers whether the internal $_timezone differs
446
     * from the set wp timezone.  If so, then it returns the datetime string formatted via
447
     * _pretty_date_format, and _pretty_time_format.  However, it also appends a timezone
448
     * abbreviation to the date_string.
449
     *
450
     * @param mixed $DateTime
451
     * @param null  $schema
452
     * @return string
453
     * @throws \EE_Error
454
     */
455
    public function prepare_for_pretty_echoing($DateTime, $schema = null)
456
    {
457
        return $this->_prepare_for_display($DateTime, $schema ? $schema : true);
458
    }
459
460
461
    /**
462
     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
463
     * timezone).
464
     *
465
     * @param DateTime    $DateTime
466
     * @param bool|string $schema
467
     * @return string
468
     * @throws \EE_Error
469
     */
470
    protected function _prepare_for_display($DateTime, $schema = false)
471
    {
472
        if (! $DateTime instanceof DateTime) {
473
            if ($this->_nullable) {
474
                return '';
475
            } else {
476
                if (WP_DEBUG) {
477
                    throw new EE_Error(
478
                        sprintf(
479
                            __(
480
                                'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.',
481
                                'event_espresso'
482
                            ),
483
                            $this->_nicename
484
                        )
485
                    );
486
                } else {
487
                    $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now);
488
                    EE_Error::add_error(
489
                        sprintf(
490
                            __(
491
                                'EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the %s field is not nullable.  When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.',
492
                                'event_espresso'
493
                            ),
494
                            $this->_nicename
495
                        )
496
                    );
497
                }
498
            }
499
        }
500
        $format_string = $this->_get_date_time_output($schema);
501
        //make sure datetime_value is in the correct timezone (in case that's been updated).
502
        $DateTime->setTimezone($this->_DateTimeZone);
503
        if ($schema) {
504
            if ($this->_display_timezone()) {
505
                //must be explicit because schema could equal true.
506
                if ($schema === 'no_html') {
507
                    $timezone_string = ' (' . $DateTime->format('T') . ')';
508
                } else {
509
                    $timezone_string = ' <span class="ee_dtt_timezone_string">(' . $DateTime->format('T') . ')</span>';
510
                }
511
            } else {
512
                $timezone_string = '';
513
            }
514
515
            return $DateTime->format($format_string) . $timezone_string;
516
        } else {
517
            return $DateTime->format($format_string);
518
        }
519
    }
520
521
522
    /**
523
     * This prepares the EE_DateTime value to be saved to the db as mysql timestamp (UTC +0
524
     * timezone).
525
     *
526
     * @param  mixed $datetime_value u
527
     * @return string mysql timestamp in UTC
528
     * @throws \EE_Error
529
     */
530
    public function prepare_for_use_in_db($datetime_value)
531
    {
532
        //we allow an empty value or DateTime object, but nothing else.
533
        if (! empty($datetime_value) && ! $datetime_value instanceof DateTime) {
534
            throw new EE_Error(
535
            	sprintf(
536
            	    __(
537
            		    'The incoming value being prepared for setting in the database must either be empty or a php 
538
            		    DateTime object, instead of: %1$s %2$s',
539
                        'event_espresso'
540
	                ),
541
                    '<br />',
542
                    print_r($datetime_value, true)
543
                )
544
            );
545
        }
546
547
        if ($datetime_value instanceof DateTime) {
548
            if ( ! $datetime_value instanceof DbSafeDateTime) {
549
                $datetime_value = DbSafeDateTime::createFromDateTime($datetime_value);
550
            }
551
552
            return $datetime_value->setTimezone($this->get_UTC_DateTimeZone())->format(
553
                EE_Datetime_Field::mysql_timestamp_format
554
            );
555
        }
556
557
        // if $datetime_value is empty, and ! $this->_nullable, use current_time() but set the GMT flag to true
558
        return ! $this->_nullable && empty($datetime_value) ? current_time('mysql', true) : null;
559
    }
560
561
562
    /**
563
     * This prepares the datetime for internal usage as a PHP DateTime object OR null (if nullable is
564
     * allowed)
565
     *
566
     * @param string $datetime_string mysql timestamp in UTC
567
     * @return  mixed null | DateTime
568
     * @throws \EE_Error
569
     */
570
    public function prepare_for_set_from_db($datetime_string)
571
    {
572
        //if $datetime_value is empty, and ! $this->_nullable, just use time()
573
        if (empty($datetime_string) && $this->_nullable) {
574
            return null;
575
        }
576
        // datetime strings from the db should ALWAYS be in UTC+0, so use UTC_DateTimeZone when creating
577
        if (empty($datetime_string)) {
578
            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
579
        } else {
580
            $DateTime = DateTime::createFromFormat(
581
                EE_Datetime_Field::mysql_timestamp_format,
582
                $datetime_string,
583
                $this->get_UTC_DateTimeZone()
584
            );
585
            if ($DateTime instanceof \DateTime) {
586
                $DateTime = new DbSafeDateTime(
587
                    $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
588
                    $this->get_UTC_DateTimeZone()
589
                );
590
            }
591
        }
592
593
        if (! $DateTime instanceof DbSafeDateTime) {
594
            // if still no datetime object, then let's just use now
595
            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->get_UTC_DateTimeZone());
596
        }
597
        // THEN apply the field's set DateTimeZone
598
        $DateTime->setTimezone($this->_DateTimeZone);
599
600
        return $DateTime;
601
    }
602
603
604
    /**
605
     * All this method does is determine if we're going to display the timezone string or not on any output.
606
     * To determine this we check if the set timezone offset is different than the blog's set timezone offset.
607
     * If so, then true.
608
     *
609
     * @return bool true for yes false for no
610
     * @throws \EE_Error
611
     */
612
    protected function _display_timezone()
613
    {
614
615
        // first let's do a comparison of timezone strings.
616
        // If they match then we can get out without any further calculations
617
        $blog_string = get_option('timezone_string');
618
        if ($blog_string === $this->_timezone_string) {
619
            return false;
620
        }
621
        // now we need to calc the offset for the timezone string so we can compare with the blog offset.
622
        $this_offset = $this->get_timezone_offset($this->_DateTimeZone);
623
        $blog_offset = $this->get_timezone_offset($this->get_blog_DateTimeZone());
624
        // now compare
625
        return $blog_offset !== $this_offset;
626
    }
627
628
629
    /**
630
     * This method returns a php DateTime object for setting on the EE_Base_Class model.
631
     * EE passes around DateTime objects because they are MUCH easier to manipulate and deal
632
     * with.
633
     *
634
     * @param int|string|DateTime $date_string            This should be the incoming date string.  It's assumed to be
635
     *                                                    in the format that is set on the date_field (or DateTime
636
     *                                                    object)!
637
     * @return DateTime
638
     */
639
    protected function _get_date_object($date_string)
640
    {
641
        //first if this is an empty date_string and nullable is allowed, just return null.
642
        if ($this->_nullable && empty($date_string)) {
643
            return null;
644
        }
645
646
        // if incoming date
647
        if ($date_string instanceof DateTime) {
648
            $date_string->setTimezone($this->_DateTimeZone);
649
650
            return $date_string;
651
        }
652
        // if empty date_string and made it here.
653
        // Return a datetime object for now in the given timezone.
654
        if (empty($date_string)) {
655
            return new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
656
        }
657
        // if $date_string is matches something that looks like a Unix timestamp let's just use it.
658
        if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $date_string)) {
659
            try {
660
                // This is operating under the assumption that the incoming Unix timestamp
661
                // is an ACTUAL Unix timestamp and not the calculated one output by current_time('timestamp');
662
                $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
663
                $DateTime->setTimestamp($date_string);
664
665
                return $DateTime;
666
            } catch (Exception $e) {
667
                // should be rare, but if things got fooled then let's just continue
668
            }
669
        }
670
        //not a unix timestamp.  So we will use the set format on this object and set timezone to
671
        //create the DateTime object.
672
        $format = $this->_date_format . ' ' . $this->_time_format;
673
        try {
674
            $DateTime = DateTime::createFromFormat($format, $date_string, $this->_DateTimeZone);
675
            if ($DateTime instanceof DateTime) {
676
                $DateTime = new DbSafeDateTime(
677
                    $DateTime->format(\EE_Datetime_Field::mysql_timestamp_format),
678
                    $this->_DateTimeZone
679
                );
680
            }
681
            if (! $DateTime instanceof DbSafeDateTime) {
682
                throw new EE_Error(
683
                    sprintf(
684
                        __('"%1$s" does not represent a valid Date Time in the format "%2$s".', 'event_espresso'),
685
                        $date_string,
686
                        $format
687
                    )
688
                );
689
            }
690
        } catch (Exception $e) {
691
            // if we made it here then likely then something went really wrong.
692
            // Instead of throwing an exception, let's just return a DateTime object for now, in the set timezone.
693
            $DateTime = new DbSafeDateTime(\EE_Datetime_Field::now, $this->_DateTimeZone);
694
        }
695
696
        return $DateTime;
697
    }
698
699
700
701
    /**
702
     * get_timezone_transitions
703
     *
704
     * @param \DateTimeZone $DateTimeZone
705
     * @param int           $time
706
     * @param bool          $first_only
707
     * @return mixed
708
     */
709
    public function get_timezone_transitions(DateTimeZone $DateTimeZone, $time = null, $first_only = true)
710
    {
711
        return EEH_DTT_Helper::get_timezone_transitions($DateTimeZone, $time, $first_only);
712
    }
713
714
715
716
    /**
717
     * get_timezone_offset
718
     *
719
     * @param \DateTimeZone $DateTimeZone
720
     * @param int           $time
721
     * @return mixed
722
     * @throws \DomainException
723
     */
724
    public function get_timezone_offset(DateTimeZone $DateTimeZone, $time = null)
725
    {
726
        return EEH_DTT_Helper::get_timezone_offset($DateTimeZone, $time);
727
    }
728
729
730
    /**
731
     * This will take an incoming timezone string and return the abbreviation for that timezone
732
     *
733
     * @param  string $timezone_string
734
     * @return string           abbreviation
735
     * @throws \EE_Error
736
     */
737
    public function get_timezone_abbrev($timezone_string)
738
    {
739
        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($timezone_string);
740
        $dateTime        = new DateTime(\EE_Datetime_Field::now, new DateTimeZone($timezone_string));
741
742
        return $dateTime->format('T');
743
    }
744
745
    /**
746
     * Overrides the parent to allow for having a dynamic "now" value
747
     *
748
     * @return mixed
749
     */
750
    public function get_default_value()
751
    {
752
        if ($this->_default_value === EE_Datetime_Field::now) {
753
            return time();
754
        } else {
755
            return parent::get_default_value();
756
        }
757
    }
758
759
760
    public function getSchemaDescription()
761
    {
762
        return sprintf(
763
            esc_html__('%s - the value for this field is in the timezone of the site.', 'event_espresso'),
764
            $this->get_nicename()
765
        );
766
    }
767
}
768