WordPress.org

Make WordPress Core

Opened 6 years ago

Closed 2 days ago

#25002 closed defect (bug) (fixed)

get_post_time() doesn't return correct GMT time if date_default_timezone_set is changed from UTC.

Reported by: johnregan3 Owned by: SergeyBiryukov
Milestone: 5.3 Priority: normal
Severity: normal Version: 1.2
Component: Date/Time Keywords: has-unit-tests has-patch
Focuses: Cc:

Description

get_post_time() and get_post_modified_time() have a parameter for GMT(UTC) time. However, they use mysqldate(), which does not take such a parameter (i.e., mysql2date expects the default time zone to be UTC).

mysql2date() uses strtotime() or date(), both of which return values relative to the default time zone (date_default_timezone_set()). So, if a developer changes the default timezone and then requests a GMT date from get_post_time() or get_post_modified_time(), they will receive an erroneous return value.

More information here: http://weston.ruter.net/2013/04/02/do-not-change-the-default-timezone-from-utc-in-wordpress/

To reproduce the problem, run the enclosed unit test. It requests a GMT time from the function twice: once while in GMT, and once in another timezone (America/Chicago). The two results should be identical because they both request GMT time, but they are not.

Just to confirm, this problem occurs when all plugins are deactivated and the default theme is used.

I am submitting two files with this ticket:

  1. A Unit Test (mysql2date.php) displaying the faults in mysql2date (and showing that the new patch fixes the issue).
  1. A Patch to fix the bug. This patch has been tested using the Unit Test above.

The patch begins by adding a fourth optional parameter to mysql2date, $gmt, which will tell the function that it needs to return a GMT value. This $gmt variable will be sent from get_post_time() and get_post_modified_time(). Then, if GMT is requested, the date_default_timezone_set is set to UTC (WP's default timezone), then conditional statements instruct mysql2date as to what value to return. There is more documentation within the patch itself.

Attachments (3)

mysql2date.diff (3.5 KB) - added by johnregan3 6 years ago.
Patch to fix mysql2date issue.
mysql2date.php (3.7 KB) - added by johnregan3 6 years ago.
Unit Test for get_post_time() and get_post_modified_time()
get-post-datetime.patch (6.4 KB) - added by Rarst 3 weeks ago.

Download all attachments as: .zip

Change History (12)

@johnregan3
6 years ago

Patch to fix mysql2date issue.

@johnregan3
6 years ago

Unit Test for get_post_time() and get_post_modified_time()

#1 @sabreuse
6 years ago

related: #21987

#2 @westonruter
6 years ago

  • Cc weston@… added

#3 @c3mdigital
6 years ago

  • Cc chris@… added
  • Version changed from 3.6 to 1.2

#4 @chriscct7
4 years ago

  • Keywords needs-patch needs-testing added; has-patch removed

#7 @Rarst
4 months ago

  • Keywords bulk-reopened added

Ok, so this touches on a lot of moving parts. I am generally proofing core against sensitivity to default time zone (see #44491 ) so those parts are getting slowly washed out.

I am looking at fixing up mysql2date (related #28992 ), but essentially it's garbage in garbage out. It was originally written to work with ambiguous timezone-less inputs and it accepts pretty much whatever, so it borders on unrealistic to clean it up into something sane.

For posts my current plan is to introduce a new get_post_datetime() function, that will instance a proper timezone-aware DateTime object from a post. Using that will knock out a lot of issues with how post times are read and output.

Last edited 4 months ago by Rarst (previous) (diff)

#8 @Rarst
3 weeks ago

  • Keywords has-unit-tests has-patch added; needs-patch needs-testing bulk-reopened removed

Ok, mysql2date() is getting fixed up some in #28992, but get_post_time() (surprise! surprise!) is broken anyway.

Really not keen on keeping using mysql2date() for GMT times, doesn't really make sense.

As planned added patch introducing get_post_datetime(), changing older functions to use it, with unit tests for old quirky logic.

This ticket was mentioned in Slack in #core-datetime by rarst. View the logs.


3 weeks ago

#10 @SergeyBiryukov
3 weeks ago

  • Milestone set to 5.3
  • Owner set to SergeyBiryukov
  • Status changed from new to reviewing

#11 @SergeyBiryukov
2 days ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 46154:

Date/Time: Introduce get_post_datetime() to retrieve post published or modified time as a DateTimeImmutable object instance.

Introduce get_post_timestamp() to retrieve post published or modified time as a Unix timestamp.

Use get_post_datetime() in get_post_time() and get_post_modified_time() to return correct GMT time if default timezone is changed from UTC.

Props Rarst, johnregan3.
Fixes #25002.

Note: See TracTickets for help on using tickets.