Skip to content
Permalink
Browse files

Date/Time: Revamp `mysql2date()` to use `wp_date()` and handle invali…

…d input in a consistent manner.

Add unit tests, improve documentation.

Props Rarst, pbearne.
Fixes #28992.

git-svn-id: https://develop.svn.wordpress.org/trunk@45908 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information...
SergeyBiryukov committed Aug 29, 2019
1 parent f490fb9 commit 71697aefc049cdc2f09c999c5bf137d6509ac16a
Showing with 101 additions and 24 deletions.
  1. +30 −24 src/wp-includes/functions.php
  2. +71 −0 tests/phpunit/tests/date/mysql2date.php
@@ -8,41 +8,46 @@
require( ABSPATH . WPINC . '/option.php' );
/**
* Convert given date string into a different format.
* Convert given MySQL date string into a different format.
*
* $format should be either a PHP date format string, e.g. 'U' for a Unix
* timestamp, or 'G' for a Unix timestamp assuming that $date is GMT.
* `$format` should be a PHP date format string.
* 'U' and 'G' formats will return a sum of timestamp with timezone offset.
* `$date` is expected to be local time in MySQL format (`Y-m-d H:i:s`).
*
* If $translate is true then the given date and format string will
* be passed to date_i18n() for translation.
* Historically UTC time could be passed to the function to produce Unix timestamp.
*
* If `$translate` is true then the given date and format string will
* be passed to `wp_date()` for translation.
*
* @since 0.71
*
* @param string $format Format of the date to return.
* @param string $date Date string to convert.
* @param bool $translate Whether the return date should be translated. Default true.
* @return string|int|bool Formatted date string or Unix timestamp. False if $date is empty.
* @return string|int|false Formatted date string or sum of Unix timestamp and timezone offset.
* False on failure.
*/
function mysql2date( $format, $date, $translate = true ) {
if ( empty( $date ) ) {
return false;
}
if ( 'G' == $format ) {
return strtotime( $date . ' +0000' );
}
$datetime = date_create( $date, wp_timezone() );
$i = strtotime( $date );
if ( false === $datetime ) {
return false;
}
if ( 'U' == $format ) {
return $i;
// Returns a sum of timestamp with timezone offset. Ideally should never be used.
if ( 'G' === $format || 'U' === $format ) {
return $datetime->getTimestamp() + $datetime->getOffset();
}
if ( $translate ) {
return date_i18n( $format, $i );
} else {
return gmdate( $format, $i );
return wp_date( $format, $datetime->getTimestamp() );
}
return $datetime->format( $format );
}
/**
@@ -58,8 +63,8 @@ function mysql2date( $format, $date, $translate = true ) {
*
* @since 1.0.0
*
* @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp', or PHP date
* format string (e.g. 'Y-m-d').
* @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp',
* or PHP date format string (e.g. 'Y-m-d').
* @param int|bool $gmt Optional. Whether to use GMT timezone. Default false.
* @return int|string Integer if $type is 'timestamp', string otherwise.
*/
@@ -151,10 +156,10 @@ function wp_timezone() {
* @global WP_Locale $wp_locale WordPress date and time locale object.
*
* @param string $format Format to display the date.
* @param int|bool $timestamp_with_offset Optional. A sum of Unix timestamp and timezone offset in seconds.
* Default false.
* @param bool $gmt Optional. Whether to use GMT timezone. Only applies if timestamp is
* not provided. Default false.
* @param int|bool $timestamp_with_offset Optional. A sum of Unix timestamp and timezone offset
* in seconds. Default false.
* @param bool $gmt Optional. Whether to use GMT timezone. Only applies
* if timestamp is not provided. Default false.
* @return string The date, translated if locale specifies it.
*/
function date_i18n( $format, $timestamp_with_offset = false, $gmt = false ) {
@@ -204,14 +209,15 @@ function date_i18n( $format, $timestamp_with_offset = false, $gmt = false ) {
*
* This is a newer function, intended to replace `date_i18n()` without legacy quirks in it.
*
* Note that, unlike `date_i18n()`, this function accepts a true Unix timestamp, not summed with timezone offset.
* Note that, unlike `date_i18n()`, this function accepts a true Unix timestamp, not summed
* with timezone offset.
*
* @since 5.3.0
*
* @param string $format PHP date format.
* @param int $timestamp Optional. Unix timestamp. Defaults to current time.
* @param DateTimeZone $timezone Optional. Timezone to output result in. Defaults to timezone from site settings.
*
* @param DateTimeZone $timezone Optional. Timezone to output result in. Defaults to timezone
* from site settings.
* @return string The date, translated if locale specifies it.
*/
function wp_date( $format, $timestamp = null, $timezone = null ) {
@@ -0,0 +1,71 @@
<?php
/**
* @group date
* @group datetime
*/
class Tests_Date_mysql2date extends WP_UnitTestCase {
function tearDown() {
date_default_timezone_set( 'UTC' );
parent::tearDown();
}
/**
* @ticket 28992
*/
function test_mysql2date_should_format_time() {
$timezone = 'Europe/Kiev';
update_option( 'timezone_string', $timezone );
$datetime = new DateTime( 'now', new DateTimeZone( $timezone ) );
$rfc3339 = $datetime->format( DATE_RFC3339 );
$mysql = $datetime->format( 'Y-m-d H:i:s' );
$this->assertEquals( $rfc3339, mysql2date( DATE_RFC3339, $mysql ) );
$this->assertEquals( $rfc3339, mysql2date( DATE_RFC3339, $mysql, false ) );
}
/**
* @ticket 28992
*/
function test_mysql2date_should_format_time_with_changed_time_zone() {
$timezone = 'Europe/Kiev';
date_default_timezone_set( $timezone );
update_option( 'timezone_string', $timezone );
$datetime = new DateTime( 'now', new DateTimeZone( $timezone ) );
$rfc3339 = $datetime->format( DATE_RFC3339 );
$mysql = $datetime->format( 'Y-m-d H:i:s' );
$this->assertEquals( $rfc3339, mysql2date( DATE_RFC3339, $mysql ) );
$this->assertEquals( $rfc3339, mysql2date( DATE_RFC3339, $mysql, false ) );
}
/**
* @ticket 28992
*/
function test_mysql2date_should_return_wp_timestamp() {
$timezone = 'Europe/Kiev';
update_option( 'timezone_string', $timezone );
$datetime = new DateTime( 'now', new DateTimeZone( $timezone ) );
$wp_timestamp = $datetime->getTimestamp() + $datetime->getOffset();
$mysql = $datetime->format( 'Y-m-d H:i:s' );
$this->assertEquals( $wp_timestamp, mysql2date( 'U', $mysql, false ) );
$this->assertEquals( $wp_timestamp, mysql2date( 'G', $mysql, false ) );
}
/**
* @ticket 28992
*/
function test_mysql2date_should_return_unix_timestamp_for_gmt_time() {
$timezone = 'Europe/Kiev';
update_option( 'timezone_string', $timezone );
$datetime = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
$timestamp = $datetime->getTimestamp();
$mysql = $datetime->format( 'Y-m-d H:i:s' );
$this->assertEquals( $timestamp, mysql2date( 'U', $mysql, false ) );
$this->assertEquals( $timestamp, mysql2date( 'G', $mysql, false ) );
}
}

0 comments on commit 71697ae

Please sign in to comment.
You can’t perform that action at this time.