Page MenuHomePhabricator

WbTime comparison is incorrect
Closed, ResolvedPublicFeature

Description

I'm doing some checks before adding the country of citizenship (P27) to persons. The check is quite simple: Did the country already exist during the lifetime of a person. Seemed to work quite well so I was puzzled to see this edit: https://www.wikidata.org/w/index.php?title=Q4271168&type=revision&diff=388967975&oldid=306952066

Peter Le Lievre (Q4271168) lived 1812-1878 and United Kingdom (Q145) has inception (P571) 12 April 1927. Why did the bot add it?

Code to reproduce:

import pywikibot
repo = pywikibot.Site().data_repository()
# Our person is Peter Le Lievre (https://www.wikidata.org/wiki/Q4271168 )
personitem = pywikibot.ItemPage(repo, u'Q4271168')
persondata = personitem.get()
personclaims = persondata.get('claims')

dateofbirth = personclaims.get(u'P569')[0].getTarget()
dateofdeath = personclaims.get(u'P570')[0].getTarget()


# Suggested country is United Kingdom ( https://www.wikidata.org/wiki/Q145 
countryitem = pywikibot.ItemPage(repo, u'Q145')
countrydata = countryitem.get()
countryclaims = countrydata.get('claims')
countryinception = countryclaims.get(u'P571')[0].getTarget()

print dateofbirth
print dateofdeath
print countryinception

# Dateofbirth is smaller than dateofdeath so I expect true here
print dateofbirth < dateofdeath

# Dateofbirth is smaller than countryinception so I expect true here
print dateofbirth < countryinception

# BUG!

Looking at https://docs.python.org/2/reference/datamodel.html#basic-customization the solution is probably to implement either cmp ( https://docs.python.org/2/reference/datamodel.html#object.__cmp__ ) or the more specific ones:

  • object.lt(self, other)
  • object.le(self, other)
  • object.eq(self, other)
  • object.ne(self, other)
  • object.gt(self, other)

*object.ge(self, other)

From the manual: " If no cmp(), eq() or ne() operation is defined, class instances are compared by object identity (“address”)."

Probably easiest to just compare the output for both toTimestr()

Related Objects

Event Timeline

Cannot follow. I used your example and got:

>>> dateofbirth
WbTime(year=1812, month=1, day=1, hour=0, minute=0, second=0, precision=9, before=0, after=0, timezone=0, calendarmodel=http://www.wikidata.org/entity/Q1985727)
>>> dateofdeath
WbTime(year=1878, month=1, day=1, hour=0, minute=0, second=0, precision=9, before=0, after=0, timezone=0, calendarmodel=http://www.wikidata.org/entity/Q1985727)
>>> countryinception
WbTime(year=1927, month=4, day=12, hour=0, minute=0, second=0, precision=11, before=0, after=0, timezone=0, calendarmodel=http://www.wikidata.org/entity/Q1985727)
>>> dateofbirth < dateofdeath
True
>>> dateofbirth < countryinception
True
>>> dateofdeath < countryinception
True
>>>

The comparison looks right. The script should be investigated but which is it?

WbTime does not has any comparison methods except __eq__() derived from WbRepresentation class. Thus any other comparisons are made by the very basic object class using its object id.

I ask myself why WbTime is not a subclass of pywikibot.Timestamp.

Xqt triaged this task as High priority.Oct 15 2016, 5:22 PM

Change 316220 had a related patch set uploaded (by Xqt):
[bugfix] Implement comparison for WbTime object

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

Part of the problem is that WbTime need to support dates such as 2010-00-00 and 2010-01-00 as (per T123888) the default month and day should both be 00 not 01 (2010-00-01 is however not allowed). There may also be problems with dates such as 0000-01-01 which is allowed (for now) in Wikibase (T94064) as well as negative years.

I don't know the current implementation, but I know how the datatype is meant to be used: Values that are outside of the precision should not be compared. For example, when comparing 2010-00-00 to 2010-01-01, where both have the precision "year", the comparison should not take the month and the day into account. The two should be considered equal.

When comparing 2010-00-00 (precision is "year") to 2010-01-00 ("month"), a standard-conform comparison algorithm might work as follows:

  • Pick the more precise precision, in this case "month".
  • Cut off both values at this precision (that is, ignore everything that is more precise). This results in 2010-00 and 2010-01.
  • Set month and day to 1, if they are zero. This results in 2010-01 for both.
  • Now do the comparison.

This is just one, but not the only way to do such a comparison. If it's "correct" or not is up to you and your use cases. The Wikibase software itself does not implement such an algorithm.

Also see T123888#3818453.

Aklapper removed Xqt as the assignee of this task.Jul 2 2021, 5:15 AM

Removing task assignee due to inactivity, as this open task has been assigned for more than two years (see emails sent to assignee on May26 and Jun17, and T270544). Please assign this task to yourself again if you still realistically [plan to] work on this task - it would be very welcome!

(See https://www.mediawiki.org/wiki/Bug_management/Assignee_cleanup for tips how to best manage your individual work in Phabricator.)

Change 863328 had a related patch set uploaded (by RPI2026F1; author: Xqt):

[pywikibot/core@master] [Bugfix] Implement comparison for WbTime object

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

RPI2026F1 lowered the priority of this task from High to Medium.Dec 8 2022, 10:39 PM

Python 3 no longer allows comparisons between WbTime so it's not going to lead to subtle errors anymore.

RPI2026F1 changed the task status from Open to In Progress.Dec 14 2022, 9:29 PM
RPI2026F1 changed the subtype of this task from "Task" to "Feature Request".

Change 863328 merged by jenkins-bot:

[pywikibot/core@master] [Bugfix] Implement comparison for WbTime object

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

Change 316220 abandoned by Xqt:

[pywikibot/core@master] [WIP][bugfix] Implement comparison for WbTime object

Reason:

https://gerrit.wikimedia.org/r/c/pywikibot/core/+/863328

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