Date/Time: Use PHP `DateTime` class API in `current_time()`.

Only use the legacy WP timestamp approach (a sum of timestamp and timezone offset) for `timestamp` and `U` formats without the `$gmt` flag.

Otherwise, make sure the function returns correct local time for any format.

Props Rarst, jdgrimes.
Fixes #40653.

git-svn-id: https://develop.svn.wordpress.org/trunk@45856 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Sergey Biryukov 2019-08-19 21:05:42 +00:00
parent f5f2fc379e
commit 91f60afbe5
2 changed files with 50 additions and 10 deletions

View File

@ -46,10 +46,11 @@ function mysql2date( $format, $date, $translate = true ) {
}
/**
* Retrieve the current time based on specified type.
* Retrieves the current time based on specified type.
*
* The 'mysql' type will return the time in the format for MySQL DATETIME field.
* The 'timestamp' type will return the current timestamp.
* The 'timestamp' type will return the current timestamp or a sum of timestamp
* and timezone offset, depending on `$gmt`.
* Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d').
*
* If $gmt is set to either '1' or 'true', then both types will use GMT time.
@ -63,14 +64,19 @@ function mysql2date( $format, $date, $translate = true ) {
* @return int|string Integer if $type is 'timestamp', string otherwise.
*/
function current_time( $type, $gmt = 0 ) {
switch ( $type ) {
case 'mysql':
return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) );
case 'timestamp':
return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
default:
return ( $gmt ) ? gmdate( $type ) : gmdate( $type, time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
// Don't use non-GMT timestamp, unless you know the difference and really need to.
if ( 'timestamp' === $type || 'U' === $type ) {
return $gmt ? time() : time() + (int) ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
}
if ( 'mysql' === $type ) {
$type = 'Y-m-d H:i:s';
}
$timezone = $gmt ? new DateTimeZone( 'UTC' ) : wp_timezone();
$datetime = new DateTime( 'now', $timezone );
return $datetime->format( $type );
}
/**

View File

@ -6,8 +6,10 @@
*/
class Tests_Date_CurrentTime extends WP_UnitTestCase {
/**
* @ticket 37440
*/
public function test_should_work_with_changed_timezone() {
$format = 'Y-m-d H:i:s';
$timezone_string = 'America/Regina';
update_option( 'timezone_string', $timezone_string );
@ -21,4 +23,36 @@ class Tests_Date_CurrentTime extends WP_UnitTestCase {
$this->assertEquals( gmdate( $format ), current_time( $format, true ) );
$this->assertEquals( $datetime->format( $format ), current_time( $format ) );
}
/**
* @ticket 40653
*/
public function test_should_return_wp_timestamp() {
update_option( 'timezone_string', 'Europe/Kiev' );
$timestamp = time();
$datetime = new DateTime( '@' . $timestamp );
$datetime->setTimezone( wp_timezone() );
$wp_timestamp = $timestamp + $datetime->getOffset();
$this->assertEquals( $timestamp, current_time( 'timestamp', true ), '', 2 );
$this->assertEquals( $timestamp, current_time( 'U', true ), '', 2 );
$this->assertEquals( $wp_timestamp, current_time( 'timestamp' ), '', 2 );
$this->assertEquals( $wp_timestamp, current_time( 'U' ), '', 2 );
$this->assertInternalType( 'int', current_time( 'timestamp' ) );
}
/**
* @ticket 40653
*/
public function test_should_return_correct_local_time() {
update_option( 'timezone_string', 'Europe/Kiev' );
$timestamp = time();
$datetime_local = new DateTime( '@' . $timestamp );
$datetime_local->setTimezone( wp_timezone() );
$datetime_utc = new DateTime( '@' . $timestamp );
$datetime_utc->setTimezone( new DateTimeZone( 'UTC' ) );
$this->assertEquals( $datetime_local->format( DATE_W3C ), current_time( DATE_W3C ), '', 2 );
$this->assertEquals( $datetime_utc->format( DATE_W3C ), current_time( DATE_W3C, true ), '', 2 );
}
}