Opened 11 months ago
Closed 7 months ago
#20942 closed defect (bug) (fixed)
get_gmt_from_date() throws exceptions
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Priority: | normal | Milestone: | 3.5 |
| Component: | Date/Time | Version: | |
| Severity: | normal | Keywords: | has-patch dev-feedback |
| Cc: |
Description
As of PHP 5.3, new DateTime( $string ) throws an exception if $string is unparseable. WordPress doesn't catch the exception.
We should either catch the exception or use date_create( $string ), which just returns false if $string is unparseable.
I don't know what we should return from get_gmt_from_date( $string ) if $string is unparseable. false? 1970? "0000-00-00 00:00:00"? In the branch that handles an empty $tz, WordPress usually returns something near "1999-11-30 00:00:00" when $string doesn't match the expected format.
$ php -r 'define( "WP_DEBUG_DISPLAY", true ); require "wp-load.php"; add_filter( "pre_option_timezone_string", function() { return "America/Los_Angeles"; } ); var_dump( get_gmt_from_date( "WordPress" ) );'
PHP Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (WordPress) at position 0 (W): The timezone could not be found in the database' in /Users/mdawaffe/Sites/wordpress/wp-includes/formatting.php:1872
Stack trace:
#0 /Users/mdawaffe/Sites/wordpress/wp-includes/formatting.php(1872): DateTime->__construct('WordPress')
#1 Command line code(1): get_gmt_from_date('WordPress')
#2 {main}
thrown in /Users/mdawaffe/Sites/wordpress/wp-includes/formatting.php on line 1872
Attachments (3)
Change History (11)
Adjusted and re-uploaded patch per suggestion from georgestephanis: "Do you need to account for a negative offset in line 1874 ? swap out '+' . $offset / 3600 . ' hours'); with ( $offset < 0 ? '-' : '+' ) . abs( $offset / 3600 ) . ' hours' ); -- perhaps? If it works as is with the + so be it, it's just my thoughts after a sixty second glance."
comment:2
wonderboymusic — 9 months ago
- Keywords has-patch added; needs-patch removed
The RegEx already checks for proper date string, so all we need to do is wrap the if / else timezone code in if ( $matches ) { .... }. I am not in love with the procedural aliases PHP offers.
Attached a patch
wonderboymusic — 9 months ago
comment:3
wonderboymusic — 9 months ago
actually, it's way simpler than that - updated. Now just have to decide if null is cool - or false or some other time should be returned.
If you pass an invalidate date (like month 13), the regular expression will be fine but the exception will be thrown.
There's no need for us to convert all of this to procedural aliases. Just the creation. So:
$datetime = date_create( $string );
if ( ! $datetime )
return something;
$datetime->setTimezone( new DateTimeZone('UTC') );
- Keywords needs-patch added; has-patch removed
Of course, if the regex fails first, we can bail just the same.
comment:7
wonderboymusic — 8 months ago
- Keywords has-patch dev-feedback added; needs-patch removed
Refreshed the patch - caveat: every place that uses this in core expects a date to be returned and possibly filtered. Also have to respect the 'format' arg. I accomplish this by returning date( $format, 0 ).

We don't like exceptions, so date_create() it is. In my mind, returning false would make the most sense for an invalid date.