Date/Time: Make sure `get_post_time()` keeps UTC time on timezone change.
Add `$source` parameter to `get_post_datetime()` to instantiate from local or UTC time in database. Props Rarst, david.binda. Reviewed by azaozz, SergeyBiryukov. Fixes #48384. git-svn-id: https://develop.svn.wordpress.org/trunk@46580 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
db4e52b923
commit
c67b47c66e
|
@ -2565,7 +2565,8 @@ function get_post_time( $d = 'U', $gmt = false, $post = null, $translate = false
|
|||
return false;
|
||||
}
|
||||
|
||||
$datetime = get_post_datetime( $post );
|
||||
$source = ( $gmt ) ? 'gmt' : 'local';
|
||||
$datetime = get_post_datetime( $post, 'date', $source );
|
||||
|
||||
if ( false === $datetime ) {
|
||||
return false;
|
||||
|
@ -2606,26 +2607,48 @@ function get_post_time( $d = 'U', $gmt = false, $post = null, $translate = false
|
|||
*
|
||||
* The object will be set to the timezone from WordPress settings.
|
||||
*
|
||||
* For legacy reasons, this function allows to choose to instantiate from local or UTC time in database.
|
||||
* Normally this should make no difference to the result. However, the values might get out of sync in database,
|
||||
* typically because of timezone setting changes. The parameter ensures the ability to reproduce backwards
|
||||
* compatible behaviors in such cases.
|
||||
*
|
||||
* @since 5.3.0
|
||||
*
|
||||
* @param int|WP_Post $post Optional. WP_Post object or ID. Default is global `$post` object.
|
||||
* @param string $field Optional. Post field to use. Accepts 'date' or 'modified'.
|
||||
* @param string $field Optional. Published or modified time to use from database. Accepts 'date' or 'modified'.
|
||||
* Default 'date'.
|
||||
* @param string $source Optional. Local or UTC time to use from database. Accepts 'local' or 'gmt'.
|
||||
* Default 'local'.
|
||||
* @return DateTimeImmutable|false Time object on success, false on failure.
|
||||
*/
|
||||
function get_post_datetime( $post = null, $field = 'date' ) {
|
||||
function get_post_datetime( $post = null, $field = 'date', $source = 'local' ) {
|
||||
$post = get_post( $post );
|
||||
|
||||
if ( ! $post ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$wp_timezone = wp_timezone();
|
||||
|
||||
if ( 'gmt' === $source ) {
|
||||
$time = ( 'modified' === $field ) ? $post->post_modified_gmt : $post->post_date_gmt;
|
||||
$timezone = new DateTimeZone( 'UTC' );
|
||||
} else {
|
||||
$time = ( 'modified' === $field ) ? $post->post_modified : $post->post_date;
|
||||
$timezone = $wp_timezone;
|
||||
}
|
||||
|
||||
if ( empty( $time ) || '0000-00-00 00:00:00' === $time ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return date_create_immutable_from_format( 'Y-m-d H:i:s', $time, wp_timezone() );
|
||||
$datetime = date_create_immutable_from_format( 'Y-m-d H:i:s', $time, $timezone );
|
||||
|
||||
if ( false === $datetime ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $datetime->setTimezone( $wp_timezone );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2637,7 +2660,8 @@ function get_post_datetime( $post = null, $field = 'date' ) {
|
|||
* @since 5.3.0
|
||||
*
|
||||
* @param int|WP_Post $post Optional. WP_Post object or ID. Default is global `$post` object.
|
||||
* @param string $field Optional. Post field to use. Accepts 'date' or 'modified'.
|
||||
* @param string $field Optional. Published or modified time to use from database. Accepts 'date' or 'modified'.
|
||||
* Default 'date'.
|
||||
* @return int|false Unix timestamp on success, false on failure.
|
||||
*/
|
||||
function get_post_timestamp( $post = null, $field = 'date' ) {
|
||||
|
@ -2729,7 +2753,8 @@ function get_post_modified_time( $d = 'U', $gmt = false, $post = null, $translat
|
|||
return false;
|
||||
}
|
||||
|
||||
$datetime = get_post_datetime( $post, 'modified' );
|
||||
$source = ( $gmt ) ? 'gmt' : 'local';
|
||||
$datetime = get_post_datetime( $post, 'modified', $source );
|
||||
|
||||
if ( false === $datetime ) {
|
||||
return false;
|
||||
|
|
|
@ -62,4 +62,51 @@ class Tests_Date_Post_Time extends WP_UnitTestCase {
|
|||
$this->assertEquals( $rfc3339, get_post_modified_time( DATE_RFC3339, false, $post_id, true ) );
|
||||
$this->assertEquals( $rfc3339_utc, get_post_modified_time( DATE_RFC3339, true, $post_id, true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 48384
|
||||
*/
|
||||
public function test_should_keep_utc_time_on_timezone_change_with_gmt_offset() {
|
||||
// Set the timezone to UTC+0.
|
||||
update_option( 'gmt_offset', 0 );
|
||||
|
||||
$datetime = new DateTimeImmutable( 'now', new DateTimeZone( 'UTC' ) );
|
||||
$mysql = $datetime->format( 'Y-m-d H:i:s' );
|
||||
$rfc3339 = $datetime->format( DATE_RFC3339 );
|
||||
$post_id = self::factory()->post->create(
|
||||
array(
|
||||
'post_date' => $mysql,
|
||||
'post_modified' => $mysql,
|
||||
)
|
||||
);
|
||||
|
||||
// Change the timezone to UTC+2.
|
||||
update_option( 'gmt_offset', 2 );
|
||||
|
||||
$this->assertEquals( $rfc3339, get_post_time( DATE_RFC3339, true, $post_id ) );
|
||||
$this->assertEquals( $rfc3339, get_post_modified_time( DATE_RFC3339, true, $post_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 48384
|
||||
*/
|
||||
public function test_should_keep_utc_time_on_timezone_change() {
|
||||
$timezone = 'UTC';
|
||||
update_option( 'timezone_string', $timezone );
|
||||
|
||||
$datetime = new DateTimeImmutable( 'now', new DateTimeZone( $timezone ) );
|
||||
$mysql = $datetime->format( 'Y-m-d H:i:s' );
|
||||
$rfc3339 = $datetime->format( DATE_RFC3339 );
|
||||
$post_id = self::factory()->post->create(
|
||||
array(
|
||||
'post_date' => $mysql,
|
||||
'post_modified' => $mysql,
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'timezone_string', 'Europe/Kiev' );
|
||||
|
||||
$this->assertEquals( $rfc3339, get_post_time( DATE_RFC3339, true, $post_id ) );
|
||||
$this->assertEquals( $rfc3339, get_post_modified_time( DATE_RFC3339, true, $post_id ) );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue