Completed
Branch BUG/pantheon-session-fatal-2 (2f2c99)
by
unknown
19:07 queued 09:56
created

EE_Datetime_Field::getDefaultDateTimeObj()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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