Make WordPress Core

Changeset 45876


Ignore:
Timestamp:
08/22/2019 03:10:05 AM (5 years ago)
Author:
SergeyBiryukov
Message:

Date/Time: Use wp_timezone() in WP_Date_Query::build_mysql_datetime() to address timezone issues.

Improve unit test coverage.

Props Rarst, Biranit, birgire, jave.web, SergeyBiryukov.
Fixes #41782.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-date-query.php

    r45850 r45876  
    854854     * You can pass an array of values (year, month, etc.) with missing parameter values being defaulted to
    855855     * either the maximum or minimum values (controlled by the $default_to parameter). Alternatively you can
    856      * pass a string that will be run through strtotime().
     856     * pass a string that will be passed to date_create().
    857857     *
    858858     * @since 3.7.0
     
    866866     */
    867867    public function build_mysql_datetime( $datetime, $default_to_max = false ) {
    868         $now = current_time( 'timestamp' );
    869 
    870868        if ( ! is_array( $datetime ) ) {
    871869
     
    908906            // If no match is found, we don't support default_to_max.
    909907            if ( ! is_array( $datetime ) ) {
    910                 // @todo Timezone issues here possibly
    911                 return gmdate( 'Y-m-d H:i:s', strtotime( $datetime, $now ) );
     908                $wp_timezone = wp_timezone();
     909
     910                // Assume local timezone if not provided.
     911                $dt = date_create( $datetime, $wp_timezone );
     912
     913                if ( false === $dt ) {
     914                    return gmdate( 'Y-m-d H:i:s', false );
     915                }
     916
     917                return $dt->setTimezone( $wp_timezone )->format( 'Y-m-d H:i:s' );
    912918            }
    913919        }
     
    916922
    917923        if ( ! isset( $datetime['year'] ) ) {
    918             $datetime['year'] = gmdate( 'Y', $now );
     924            $datetime['year'] = current_time( 'Y' );
    919925        }
    920926
  • trunk/tests/phpunit/tests/date/query.php

    r45607 r45876  
    510510    }
    511511
    512     public function test_build_mysql_datetime_default_to_max_true() {
    513         $q = new WP_Date_Query( array() );
    514 
    515         $found = $q->build_mysql_datetime(
    516             array(
    517                 'year' => 2011,
    518             ),
    519             true
    520         );
    521         $this->assertSame( '2011-12-31 23:59:59', $found );
    522     }
    523 
    524     public function test_build_mysql_datetime_default_to_max_false() {
    525         $q = new WP_Date_Query( array() );
    526 
    527         $found = $q->build_mysql_datetime(
    528             array(
    529                 'year' => 2011,
    530             ),
    531             false
    532         );
    533         $this->assertSame( '2011-01-01 00:00:00', $found );
    534     }
    535 
    536     public function test_build_mysql_datetime_default_to_max_default_to_false() {
    537         $q = new WP_Date_Query( array() );
    538 
    539         $found = $q->build_mysql_datetime(
    540             array(
    541                 'year' => 2011,
    542             ),
    543             false
    544         );
    545         $this->assertSame( '2011-01-01 00:00:00', $found );
     512    /**
     513     * @ticket 41782
     514     *
     515     * @dataProvider mysql_datetime_input_provider
     516     *
     517     * @param array|string $datetime       Array or string date input.
     518     * @param string       $expected       Expected built result.
     519     * @param bool         $default_to_max Flag to default missing values to max.
     520     */
     521    public function test_build_mysql_datetime( $datetime, $expected, $default_to_max = false ) {
     522        $q = new WP_Date_Query( array() );
     523
     524        $found = $q->build_mysql_datetime( $datetime, $default_to_max );
     525
     526        $message = "Expected {$expected}, got {$found}";
     527        $this->assertEquals( strtotime( $expected ), strtotime( $found ), $message, 10 );
     528    }
     529
     530    public function mysql_datetime_input_provider() {
     531        return array(
     532            array( '2019-06-04T08:18:24+03:00', '2019-06-04 05:18:24' ),
     533            array( '2019-06-04T05:18:24+00:00', '2019-06-04 05:18:24' ),
     534            array( array(), current_time( 'Y' ) . '-01-01 00:00:00' ),
     535            array( array( 'year' => 2011 ), '2011-12-31 23:59:59', true ),
     536            array( array( 'year' => 2011 ), '2011-01-01 00:00:00' ),
     537            array( '2011', '2011-01-01 00:00:00' ),
     538            array( '2011-02', '2011-02-01 00:00:00' ),
     539            array( '2011-02-03', '2011-02-03 00:00:00' ),
     540            array( '2011-02-03 13:30', '2011-02-03 13:30:00' ),
     541            array( '2011-02-03 13:30:35', '2011-02-03 13:30:35' ),
     542        );
     543    }
     544
     545    /**
     546     * @ticket 41782
     547     *
     548     * @dataProvider mysql_datetime_input_provider_custom_timezone
     549     *
     550     * @param array|string $datetime       Array or string date input.
     551     * @param string       $expected       Expected built result.
     552     * @param bool         $default_to_max Flag to default missing values to max.
     553     */
     554    public function test_build_mysql_datetime_with_custom_timezone( $datetime, $expected, $default_to_max = false ) {
     555        update_option( 'timezone_string', 'Europe/Kiev' );
     556
     557        $q = new WP_Date_Query( array() );
     558
     559        $found = $q->build_mysql_datetime( $datetime, $default_to_max );
     560
     561        $message = "Expected {$expected}, got {$found}";
     562        $this->assertEquals( strtotime( $expected ), strtotime( $found ), $message, 10 );
     563
     564    }
     565
     566    public function mysql_datetime_input_provider_custom_timezone() {
     567        return array(
     568            array( '2019-06-04T08:18:24+03:00', '2019-06-04 08:18:24' ),
     569            array( '2019-06-04T05:18:24+00:00', '2019-06-04 08:18:24' ),
     570        );
     571    }
     572
     573    /**
     574     * @ticket 41782
     575     */
     576    public function test_build_mysql_datetime_with_relative_date() {
     577        update_option( 'timezone_string', 'Europe/Kiev' );
     578
     579        $q = new WP_Date_Query( array() );
     580
     581        $yesterday = new DateTimeImmutable( '-1 day', wp_timezone() );
     582        $expected  = $yesterday->format( 'Y-m-d H:i:s' );
     583        $found     = $q->build_mysql_datetime( '-1 day' );
     584
     585        $message = "Expected {$expected}, got {$found}";
     586        $this->assertEquals( strtotime( $expected ), strtotime( $found ), $message, 10 );
    546587    }
    547588
Note: See TracChangeset for help on using the changeset viewer.