summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorSergey Biryukov <sergeybiryukov@git.wordpress.org>2019-10-25 13:06:29 +0000
committerSergey Biryukov <sergeybiryukov@git.wordpress.org>2019-10-25 13:06:29 +0000
commitc67b47c66ed357287a44f07ae93f6c139c5cdd17 (patch)
tree36eb6e3e10d1f9eae3417a5f8f4ab40d8036bc43
parentdb4e52b923322155521b054e8079fd1a270af8c7 (diff)
downloadwordpress-c67b47c66ed357287a44f07ae93f6c139c5cdd17.tar.gz
wordpress-c67b47c66ed357287a44f07ae93f6c139c5cdd17.zip
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
-rw-r--r--src/wp-includes/general-template.php41
-rw-r--r--tests/phpunit/tests/date/postTime.php47
2 files changed, 80 insertions, 8 deletions
diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php
index 32d5595bb1..f9b5661f09 100644
--- a/src/wp-includes/general-template.php
+++ b/src/wp-includes/general-template.php
@@ -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 int|WP_Post $post Optional. WP_Post object or ID. Default is global `$post` object.
+ * @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;
}
- $time = ( 'modified' === $field ) ? $post->post_modified : $post->post_date;
+ $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;
diff --git a/tests/phpunit/tests/date/postTime.php b/tests/phpunit/tests/date/postTime.php
index 02da7b5487..14115704ae 100644
--- a/tests/phpunit/tests/date/postTime.php
+++ b/tests/phpunit/tests/date/postTime.php
@@ -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 ) );
+ }
}