jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/863328 )

Change subject: [Bugfix] Implement comparison for WbTime object
......................................................................

[Bugfix] Implement comparison for WbTime object

- I used changeset 316220 as a basis for the tests
- For the sake of simplicity, all of the other changes
in the changeset were omitted
- This implementation does not change any current attributes
- This implementation factors in the correct number of days
in a month
- This implementation factors in leap years and the calendar model
when calculating leap years
- Note the difference in behavior of __ge__/__le__ and __eq__/__ne__

Bug: T148280
Change-Id: I694886fd4b264e97c351a8b2a5aefd2b5878be69
---
M pywikibot/__init__.py
M tests/wikibase_tests.py
2 files changed, 127 insertions(+), 1 deletion(-)

Approvals:
  Matěj Suchánek: Looks good to me, but someone else must approve
  RPI2026F1: Looks good to me, but someone else must approve
  Xqt: Looks good to me, approved
  jenkins-bot: Verified




diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index db7bdfe..9202523 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -319,6 +319,21 @@
     _items = ('year', 'month', 'day', 'hour', 'minute', 'second',
               'precision', 'before', 'after', 'timezone', 'calendarmodel')

+    _month_offset = {
+        1: 0,
+        2: 31,  # Jan -> Feb: 31 days
+        3: 59,  # Feb -> Mar: 28 days, plus 31 days in Jan -> Feb
+        4: 90,  # Mar -> Apr: 31 days, plus 59 days in Jan -> Mar
+        5: 120,  # Apr -> May: 30 days, plus 90 days in Jan -> Apr
+        6: 151,  # May -> Jun: 31 days, plus 120 days in Jan -> May
+        7: 181,  # Jun -> Jul: 30 days, plus 151 days in Jan -> Jun
+        8: 212,  # Jul -> Aug: 31 days, plus 181 days in Jan -> Jul
+        9: 243,  # Aug -> Sep: 31 days, plus 212 days in Jan -> Aug
+        10: 273,  # Sep -> Oct: 30 days, plus 243 days in Jan -> Sep
+        11: 304,  # Oct -> Nov: 31 days, plus 273 days in Jan -> Oct
+        12: 334,  # Nov -> Dec: 30 days, plus 304 days in Jan -> Nov
+    }
+
     def __init__(self,
                  year: Optional[int] = None,
                  month: Optional[int] = None,
@@ -349,6 +364,12 @@
           of the event, in the range −180° to 180°, multiplied by 4 to convert
           to minutes.

+        Comparison information: When using the greater than or equal to
+        operator, or the less than or equal to operator, two different time
+        objects with the same UTC time after factoring in timezones are
+        considered equal. However, the equality operator will return false
+        if the timezone is different.
+
         :param year: The year as a signed integer of between 1 and 16 digits.
         :param month: Month of the timestamp, if it exists.
         :param day: Day of the timestamp, if it exists.
@@ -406,7 +427,6 @@
                                      .format(Site()))
             calendarmodel = site.calendarmodel()
         self.calendarmodel = calendarmodel
-
         # if precision is given it overwrites the autodetection above
         if precision is not None:
             if (isinstance(precision, int)
@@ -418,6 +438,61 @@
             else:
                 raise ValueError(f'Invalid precision: "{precision}"')

+    def _getSecondsAdjusted(self) -> int:
+        """Return an internal representation of the time object as seconds.
+
+        The value adjusts itself for timezones. It is not compatible with
+        before/after.
+
+        This value should *only* be used for comparisons, and
+        its value may change without warning.
+
+        :return: An integer roughly representing the number of seconds
+            since January 1, 0000 AD, adjusted for leap years.
+        """
+        # This function ignores leap seconds. Since it is not required
+        # to correlate to an actual UNIX timestamp, this is acceptable.
+
+        # We are always required to have a year.
+        elapsed_seconds = int(self.year * 365.25 * 24 * 60 * 60)
+        if self.month > 1:
+            elapsed_seconds += self._month_offset[self.month] * 24 * 60 * 60
+            # The greogrian calendar
+            if self.calendarmodel == 'http://www.wikidata.org/entity/Q1985727':
+                if (self.year % 400 == 0
+                        or (self.year % 4 == 0 and self.year % 100 != 0)
+                        and self.month > 2):
+                    elapsed_seconds += 24 * 60 * 60  # Leap year
+            # The julian calendar
+            if self.calendarmodel == 'http://www.wikidata.org/entity/Q1985786':
+                if self.year % 4 == 0 and self.month > 2:
+                    elapsed_seconds += 24 * 60 * 60
+        if self.day > 1:
+            # Days start at 1, not 0.
+            elapsed_seconds += (self.day - 1) * 24 * 60 * 60
+        elapsed_seconds += self.hour * 60 * 60
+        elapsed_seconds += self.minute * 60
+        elapsed_seconds += self.second
+        if self.timezone is not None:
+            elapsed_seconds += self.timezone * 60
+        return elapsed_seconds
+
+    def __lt__(self, other):
+        """Compare if self is less than other."""
+        return self._getSecondsAdjusted() < other._getSecondsAdjusted()
+
+    def __le__(self, other):
+        """Compare if self is less equals other."""
+        return self._getSecondsAdjusted() <= other._getSecondsAdjusted()
+
+    def __gt__(self, other):
+        """Compare if self is greater than other."""
+        return self._getSecondsAdjusted() > other._getSecondsAdjusted()
+
+    def __ge__(self, other):
+        """Compare if self is greater equals other."""
+        return self._getSecondsAdjusted() >= other._getSecondsAdjusted()
+
     @classmethod
     def fromTimestr(cls: Type['WbTime'],
                     datetimestr: str,
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index c97f6f7..3867219 100755
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -378,6 +378,37 @@
         with self.assertRaisesRegex(ValueError, regex):
             pywikibot.WbTime(site=repo, precision='invalid_precision')

+    def test_comparison(self):
+        """Test WbTime comparison."""
+        repo = self.get_repo()
+        t1 = pywikibot.WbTime(site=repo, year=2010, hour=12, minute=43)
+        t2 = pywikibot.WbTime(site=repo, year=-2005, hour=16, minute=45)
+        self.assertEqual(t1.precision, pywikibot.WbTime.PRECISION['minute'])
+        self.assertEqual(t1, t1)
+        self.assertGreaterEqual(t1, t1)
+        self.assertGreaterEqual(t1, t2)
+        self.assertGreater(t1, t2)
+        self.assertEqual(t1.year, 2010)
+        self.assertEqual(t2.year, -2005)
+        self.assertEqual(t1.month, 1)
+        self.assertEqual(t2.month, 1)
+        self.assertEqual(t1.day, 1)
+        self.assertEqual(t2.day, 1)
+        self.assertEqual(t1.hour, 12)
+        self.assertEqual(t2.hour, 16)
+        self.assertEqual(t1.minute, 43)
+        self.assertEqual(t2.minute, 45)
+        self.assertEqual(t1.second, 0)
+        self.assertEqual(t2.second, 0)
+        self.assertEqual(t1.toTimestr(), '+00000002010-01-01T12:43:00Z')
+        self.assertEqual(t2.toTimestr(), '-00000002005-01-01T16:45:00Z')
+        self.assertRaises(ValueError, pywikibot.WbTime, site=repo,
+                          precision=15)
+        self.assertRaises(ValueError, pywikibot.WbTime, site=repo,
+                          precision='invalid_precision')
+        self.assertIsInstance(t1.toTimestamp(), pywikibot.Timestamp)
+        self.assertRaises(ValueError, t2.toTimestamp)
+

 class TestWbQuantity(WbRepresentationTestCase):


--
To view, visit https://gerrit.wikimedia.org/r/c/pywikibot/core/+/863328
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I694886fd4b264e97c351a8b2a5aefd2b5878be69
Gerrit-Change-Number: 863328
Gerrit-PatchSet: 17
Gerrit-Owner: RPI2026F1 <[email protected]>
Gerrit-Reviewer: Matěj Suchánek <[email protected]>
Gerrit-Reviewer: RPI2026F1 <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to