WordPress.org

Make WordPress Core

Opened 9 years ago

Closed 8 years ago

Last modified 8 years ago

#8662 closed defect (bug) (fixed)

current_time('timestamp') doesn't return the correct timestamp value

Reported by: hudatoriq Owned by: hudatoriq
Milestone: 2.9 Priority: high
Severity: major Version: 2.7
Component: Date/Time Keywords: has-patch needs-testing
Focuses: Cc:

Description

If we pass 'timestamp' parameter into function current_time() we get the current time in server timezone. Should be in the blog timezone or in GMT (if the $gmt value is true).

We should use the gmdate() function instead of time(), like the function does when receiving 'mysql' parameter.

I'm gonna attach a patch for this in a moment.

Attachments (3)

wp_current_time.diff (1.2 KB) - added by hudatoriq 9 years ago.
Replace time() function
8662-wp_current_time-2.patch (506 bytes) - added by hakre 9 years ago.
additional type providing the current time as timestamp gmt based.
8662.diff (831 bytes) - added by Denis-de-Bernardy 9 years ago.

Download all attachments as: .zip

Change History (48)

@hudatoriq
9 years ago

Replace time() function

#1 @hudatoriq
9 years ago

I hope this will go to 2.7.1. I submitted a patch that will fix the 2.7 branch & the trunk

#2 @hudatoriq
9 years ago

  • Keywords has-patch added; current time timestamp removed

#3 @hudatoriq
9 years ago

  • Cc westi markjaquith added

Is there any core dev watching this ticket? It's a simple bug, and has a patch. It only needs a few seconds to review it.

Actually I found it while developing my site running WPMU + buddypress. The buddypress uses timestamp to count time difference to create 'time since' string. And I need it to be fixed in WPMU soon. Should I post another ticket to WPMU trac? And is it possible to have it fixed in WPMU 2.7 (not 2.7.1)?

Thank you in advance.

#4 @mrmist
9 years ago

  • Cc westi markjaquith removed
  • Keywords dev-feedback added

#5 @hakre
9 years ago

Well, the according docblock does not state that 'timestamp' should return the current time 'in GMT', it must return the current timestamp. I can not see GMT anywhere there.

I would suggest to add another $type = 'timestampgmt' that will return what you are looking for. buddypress (and other plugins) can use it then. otherwise those plugins coul wrap this function and create such a calculation on their own.

@hakre
9 years ago

additional type providing the current time as timestamp gmt based.

#6 follow-up: @DD32
9 years ago

Well, the according docblock does not state that 'timestamp' should return the current time 'in GMT', it must return the current timestamp. I can not see GMT anywhere there.

Well, Looking at the source for timestamp, Its specifically adding the GMT offset of the blog, So the result should be the current timestamp in that timezone.

If the servers Timezone is set to anything other than GMT, then the function as it is, will return a inaccurate result.

Ok, and Hakre, Didnt notice the $gmt variable i guess? No need for a tiemstampgmt, as the 2 options currently are supposed to be: timestamp+gmt=false(in blog timezone), or timestamp+gmt=true(in gmt timezone)

#7 @Denis-de-Bernardy
9 years ago

  • Keywords tested added
  • Milestone changed from 2.7.2 to 2.8

+1 to the first wp_current_time.diff

#8 @Denis-de-Bernardy
9 years ago

the time() call on the previous line would need to be changed too, though

#9 @Denis-de-Bernardy
9 years ago

  • Keywords commit added; dev-feedback removed

#11 @westi
9 years ago

  • Cc westi added
  • Keywords reporter-feedback added; tested commit removed
  • Priority changed from high to normal
  • Severity changed from major to normal

I'm stareing hard at this trying to work out what the bug your trying to fix is.

Can you explain simply, with example what you are expected the code to do and what is does wrong?

#12 @Denis-de-Bernardy
9 years ago

  • Keywords tested added; reporter-feedback removed
  • Priority changed from normal to high
  • Severity changed from normal to major

he's complaining that, on some/all servers, time() does not return a gm time, but the server time instead.

there are many areas in WP (see #9588) where WP assumes that time() returns a GMT time, where in fact it returns the server time.

On my laptop, for instance:

var_dump(time() == strtotime(gmdate("Y-m-d H:i:s"))); // false

I may be wrong of course, but I'm willing to take the bet that multitudes of cron and autosave related bugs are related to this and #9588. In particular ones where cron doesn't get fired when expected to, and autosaves that seem to get stored with a date set in the future.

#13 @ryan
9 years ago

  • Component changed from General to Date/Time

#14 @Denis-de-Bernardy
8 years ago

  • Keywords commit added

#15 in reply to: ↑ 6 @hakre
8 years ago

Replying to DD32:

Ok, and Hakre, Didnt notice the $gmt variable i guess? No need for a tiemstampgmt, as the 2 options currently are supposed to be: timestamp+gmt=false(in blog timezone), or timestamp+gmt=true(in gmt timezone)

Jup confirmed, voerseeing that properly. for timestamp with $gmt == true time() is used but this must be GMT. same for the offset option, time() is used which fails when it is _not_ GMT.

#16 @hakre
8 years ago

+1 for 8662.diff by Denis-de-Bernardy.

#17 @ryan
8 years ago

All of these patches break for me when the blog offset does not match the server offset.

#18 @Denis-de-Bernardy
8 years ago

  • Keywords needs-testing added; tested commit removed
  • Milestone changed from 2.8 to 2.9

let's postpone all of it to 2.9 then

#19 @Denis-de-Bernardy
8 years ago

  • Keywords needs-patch added; has-patch removed

#20 @ryan
8 years ago

Actually, wp_current_time.diff might be right. Depends on what function you use to display the timestamp. Everything wants to jiggle the offset as it comes through.

#21 @Denis-de-Bernardy
8 years ago

  • Keywords has-patch added; needs-patch removed

Well... the mysql gmtime is erroneous too (which is why I added 8662.diff).

Trouble is, this is devastatingly bug prone if, in the WP internals, server time vs gmtime diffs are worked out on the fly, as you seem to have suggested in #9588.

#22 @Denis-de-Bernardy
8 years ago

Oh, part of the reason you might be seeing wp_current_time.diff as right might have a lot to do with it too. Since server times are used all over in WP internals, where its says GMT times in the docs, then surely not fixing the GMT time makes sense. :-)

the thing to look into is that current_time(timestamp, true) isn't or is barely used, as a matter of fact.

#23 @ryan
8 years ago

I'm testing directly against current_time(). 'mysql' always looks good with wp_current_time.diff or with no patch at all. 'timestamp' differs between wp_current_time.diff and no patch by the offset selected in general settings. wp_current_time.diff displays correctly when date() is used(), incorrectly when gmdate() us used. strtotime() on a mysql timestamp yields the same results as 'timestamp' with wp_current_time.diff. I'm thinking wp_current_time.diff is correct.

#24 @ryan
8 years ago

If I copy the timestamps generated by current_time('timestamp', true|false) into an online unix timestamp to date converter, the unpatched current_time() produces the correct times.

#25 follow-up: @Otto42
8 years ago

Note that here: http://core.trac.wordpress.org/browser/trunk/wp-includes/functions.php?rev=10753#L3063

If you're using the new timezone functionality, it's calling date_default_timezone_set(). This should be forcing the time() function to return the local timezone, not the GMT time. This is new functionality, added by the new timezone support in [10753].

If it is not desirable for time() to return blog local time, then line 3063 there needs to be removed. This won't affect the timezone additions.

This could be the cause of several different time related issues. Try commenting that line out, see if the time problems go away. Because before that was added, WordPress never set the default timezone in PHP.

#26 in reply to: ↑ 25 @hakre
8 years ago

Replying to Otto42:

Note that here: http://core.trac.wordpress.org/browser/trunk/wp-includes/functions.php?rev=10753#L3063 [...]

your patch is not properly working with PHP < 5.2.0. The patch in this ticket is. Since the other patch is already in, this patch needs to be extended to check against the new functions.

#27 follow-up: @hakre
8 years ago

Otto: Please keep in mind that WordPress has to work with PHP 4.3.

#28 @ryan
8 years ago

date_default_timezone_set() will change what gmdate() and date() output when given current_time(). The timestamps produced with the unpatched current_time() do not change with date_default_timezone_set(), however. They are always correct. The two different patches get the timestamps wrong.

#29 @hakre
8 years ago

Question: can the blog timezone be another timezone then the server timezone? or hast blog-timezone to be the servers timezone (because the blog is running on the server).

#30 @ryan
8 years ago

time() returns UTC for me, BTW.

#31 @ryan
8 years ago

The blog and server timezones can be different. The best way to test these time bugs is to set the blog offset to something different than the server offset.

#32 in reply to: ↑ 27 @Otto42
8 years ago

Replying to hakre:

Otto: Please keep in mind that WordPress has to work with PHP 4.3.

The patch for timezone support works perfectly with PHP 4.3, as it checks for compatibility before doing anything. Older PHP systems see no changes and that code does not activate. All that code has been tested and approved as far as that goes.

The only way you'd see a difference is in PHP 5 and up, and I'm saying that I'd check to see if removing that date_default_timezone_set line fixes the problems being seen. Because it could be the cause of them. That's all I'm saying, really.

#33 @ryan
8 years ago

Unpatched WP trunk running php5 with tz support:

Blog Offset: -5
Default TZ: America/Chicago
time() : 1240956111
current_time('mysql'): 2009-04-28 17:01:51
current_time('mysql', true): 2009-04-28 22:01:51
current_time('timestamp'): 1240938111
date('M d Y H:i:s', current_time('timestamp')): Apr 28 2009 12:01:51
gmdate('M d Y H:i:s', current_time('timestamp')): Apr 28 2009 17:01:51
current_time('timestamp', true): 1240956111
date('M d Y H:i:s', current_time('timestamp', true)): Apr 28 2009 17:01:51
gmdate('M d Y H:i:s', current_time('timestamp', true)): Apr 28 2009 22:01:51 

#34 @ryan
8 years ago

Without date_default_timezone_set()

Blog Offset: -5
Default TZ: America/Los_Angeles
time() : 1240956252
current_time('mysql'): 2009-04-28 17:04:12
current_time('mysql', true): 2009-04-28 22:04:12
current_time('timestamp'): 1240938252
date('M d Y H:i:s', current_time('timestamp')): Apr 28 2009 10:04:12
gmdate('M d Y H:i:s', current_time('timestamp')): Apr 28 2009 17:04:12
current_time('timestamp', true): 1240956252
date('M d Y H:i:s', current_time('timestamp', true)): Apr 28 2009 15:04:12
gmdate('M d Y H:i:s', current_time('timestamp', true)): Apr 28 2009 22:04:12 

#35 @ryan
8 years ago

Looks like time() is expected to be UTC, which matches the docs: "Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)."

Likewise, date() and gmdate() expect timestamps to be UTC.

#36 @Otto42
8 years ago

Bingo!

date('M d Y H:i:s', current_time('timestamp')): Apr 28 2009 12:01:51
date('M d Y H:i:s', current_time('timestamp')): Apr 28 2009 10:04:12

date('M d Y H:i:s', current_time('timestamp', true)): Apr 28 2009 17:01:51
date('M d Y H:i:s', current_time('timestamp', true)): Apr 28 2009 15:04:12

There's your two hour difference. date takes the current time zone into account, and the current time zone is different between the two.

#37 @Otto42
8 years ago

Hah. What's really odd there, is that the unpatched one, with the correct TZ support, is the one giving you the correct answers. You're in America/Chicago, which is right now about 5 pm. After you removed the date_default_timezone_set line, date() started giving you the wrong info, 2 hours earlier. This suggests that your server is in the Pacific Timezone, I'd bet. San Fran? ;)

#38 @ryan
8 years ago

What this suggests is that current_time() is doing the right thing. The problems lie in how current_time() is consumed elsewhere.

#39 @ryan
8 years ago

Passing current_time() to date() or gmdate() is useless, it seems. Just use time().

#40 @ryan
8 years ago

date_i18n() is probably a source of problems. Instead of always passing UTC timestamps, it takes ones already adjusted to local time and then forces gmdate() on them instead of just using date().

$date = date_i18n( $datef, strtotime( current_time('mysql') ) );

#41 @ryan
8 years ago

  • Milestone 2.9 deleted
  • Resolution set to invalid
  • Status changed from new to closed

Closing this ticket as invalid since current_time() appears to be doing the right thing and the proposed patches make use of strtotime(), which is subject to the default timezone setting.

#42 @Denis-de-Bernardy
8 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

#43 @lloydbudd
8 years ago

  • Milestone set to 3.0

#44 @Denis-de-Bernardy
8 years ago

  • Milestone changed from 3.0 to 2.9
  • Resolution set to fixed
  • Status changed from reopened to closed

I believe this is fixed in r12315

#45 @hakre
8 years ago

see also #11414

Note: See TracTickets for help on using tickets.