Page MenuHomePhabricator

BlockLogFormatter formats relative timestamps with duration since Unix epoch
Closed, ResolvedPublic

Description

(Very likely Regression from 01936fa)

MediaWiki thinks a block duration of "2 days" is an absolute timestamp, thus using an expiry since Unix epoch.
MediaWiki formats block duration of "2 days" as a duration since Unix epoch (4 decades, 7 years)

Reported on Commons AN. I also did a blocking test to my test account, and "day" was not the only affected unit.

This bug affects the block log entry display only, not the actual block itself or the database record of the log entry.

Event Timeline

zhuyifei1999 renamed this task from BlockLogFormatter confusing relative timestamps with absolute timestamps to BlockLogFormatter formats relative timestamps with duration since Unix epoch.Jan 27 2017, 8:38 AM
zhuyifei1999 claimed this task.
zhuyifei1999 updated the task description. (Show Details)

Problem is not relative timestamps gets confused with absolute timestamp, but $this->formatDuration( $time ); with $time absolute when it's supposed to be relative

Change 334509 had a related patch set uploaded (by Zhuyifei1999):
BlockLogFormatter: Duration is difference between current time and block expiry

https://gerrit.wikimedia.org/r/334509

I mean it would be much better if the function gets a number like time var, instead of an English text string (which was the origin of this strange bug)! Is this not possible?

I mean it would be much better if the function gets a number like time var, instead of an English text string (which was the origin of this strange bug)! Is this not possible?

The log entry in question is quarry 15830. It's parameters are a:2:{s:11:"5::duration";s:6:"2 days";s:8:"6::flags";s:17:"anononly,nocreate";} (in more readable JSON: {"duration":"2 days","flags":"anononly,nocreate"}), where 2 days is the original input during the block.

Change 334509 merged by jenkins-bot:
translateBlockExpiry: Duration is block expiry minus current time

https://gerrit.wikimedia.org/r/334509

matmarex removed a project: Patch-For-Review.

Thank you for the fix! I scheduled this change for deployment on Monday (https://wikitech.wikimedia.org/wiki/Deployments#deploycal-item-20170130T1400).

I mean it would be much better if the function gets a number like time var, instead of an English text string (which was the origin of this strange bug)! Is this not possible?

This text comes pretty much directly from whatever the user inputs in the freetext "Expiration" field on Special:Block. We could, with some effort, change it so that for custom durations, instead of typing in e.g. "2 days", the user would select date and time from a calendar (or something such), but I've got a feeling the users wouldn't appreciate that very much.

I mean it would be much better if the function gets a number like time var, instead of an English text string (which was the origin of this strange bug)! Is this not possible?

This text comes pretty much directly from whatever the user inputs in the freetext "Expiration" field on Special:Block. We could, with some effort, change it so that for custom durations, instead of typing in e.g. "2 days", the user would select date and time from a calendar (or something such), but I've got a feeling the users wouldn't appreciate that very much.

This shouldn't be necessary, since MediaWiki already translates the entered duration to a timestamp.

The ipblocks table has the timestamp where the block was issued, and the timestamp of the expiry. From here we could calculate the difference between both dates and get the number of years, months, days, hours, etc of the duration, which could be presented translated in any language.

For what I see in the log_params description, we don't have the expiry time timestamp in the logging table, just the duration as entered by the user, so an improvement would be to have the expiry as a timestamp too. But that's of course another different task

Can't that fix be cherry-picked to the current mw-wmf branch and have this fixed now? Apologies if already done.

This shouldn't be necessary, since MediaWiki already translates the entered duration to a timestamp.

The ipblocks table has the timestamp where the block was issued, and the timestamp of the expiry. From here we could calculate the difference between both dates and get the number of years, months, days, hours, etc of the duration, which could be presented translated in any language.

For what I see in the log_params description, we don't have the expiry time timestamp in the logging table, just the duration as entered by the user, so an improvement would be to have the expiry as a timestamp too. But that's of course another different task

IMO, logs of reblocks would look terrible in that case.

MediaWiki (more specifically, PHP strtotime) handles a few different types of timestamps:

  • Relative timestamps: eg. 2 days, most blocks are using these
  • Absolute timestamps: eg. Sat, 27 May 2017 07:58:26 GMT, usually used when you reblock a user (i.e. change block settings of an already blocked user)
  • Partial timestamps: eg. 10 September is 10 September 00:00 UTC in the year of the block; this one is rarely used.

The first one should be formatted relatively because A (talk | contribs | block) blocked B (talk | contribs) with an expiration at Sat, 27 May 2017 07:58:26 GMT is counter intuitive, one must do some extra calculation to know the block duration.

The other two should be formatted absolute because A (talk | contribs | block) blocked B (talk | contribs) with an expiration time of 6 days, 22 hours, 26 minutes and 2 seconds is also counter intuitive, one must do some extra calculation to know absolute expiry.

Now you may wonder why we shouldn't just simply display whatever the input is. This is undesirable because:

  • strtotime can be weird at times, or the block input could be ambiguous, and the log would not tell the true blocking time. Eg. a potato is a valid timestamp (T133438#2232086). For reference:
> echo wfTimestamp( TS_DB, time() );
2017-01-29 04:31:04
> echo wfTimestamp( TS_DB, strtotime( 'a potato', time() ) );
2017-01-29 03:31:04
  • No localization of the block expiry could be performed.

(...)

MediaWiki (more specifically, PHP strtotime) handles a few different types of timestamps:

  • Relative timestamps: eg. 2 days, most blocks are using these
  • Absolute timestamps: eg. Sat, 27 May 2017 07:58:26 GMT, usually used when you reblock a user (i.e. change block settings of an already blocked user)
  • Partial timestamps: eg. 10 September is 10 September 00:00 UTC in the year of the block; this one is rarely used.

The first one should be formatted relatively because A (talk | contribs | block) blocked B (talk | contribs) with an expiration at Sat, 27 May 2017 07:58:26 GMT is counter intuitive, one must do some extra calculation to know the block duration.

The other two should be formatted absolute because A (talk | contribs | block) blocked B (talk | contribs) with an expiration time of 6 days, 22 hours, 26 minutes and 2 seconds is also counter intuitive, one must do some extra calculation to know absolute expiry.

Yeah, I also though that. It could be solved by also storing a flag to know if the expiry time was relative or absolute, and then display one format or the other.

hashar subscribed.

This is not fixed on Wikimedia production.

Change 335019 had a related patch set uploaded (by Hashar):
translateBlockExpiry: Duration is block expiry minus current time

https://gerrit.wikimedia.org/r/335019

Change 335019 merged by jenkins-bot:
translateBlockExpiry: Duration is block expiry minus current time

https://gerrit.wikimedia.org/r/335019

Mentioned in SAL (#wikimedia-operations) [2017-01-30T14:45:53Z] <hashar@tin> Synchronized php-1.29.0-wmf.9/languages/Language.php: translateBlockExpiry: Duration is block expiry minus current time - T156453 (duration: 00m 42s)

The fix has been pushed to the Wikimedia cluster a minute or so ago. Can someone validate the block duration is now valid ? =)