Xqt has uploaded a new change for review.

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

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

[bugfix] Implement comparison for WbTime object

Also some improvements are done:
- Time information is held by a Timestamp object. This enables an easy way
  to implement adding and subtracting WbTime objects further.
- In case of the date is outside the datetime year range (1..9999)
  the year is held by an instance variable and a dummy year (2000) is used
  for the internal _timestamp.
- Use is_datetime_year() method to check whether the WbTime is inside
  the datetime year range
- Use toTimestamp to get the Timestamp object
- The year property gives the year. All other properties (month, day, hour,
  minute, second) are fetched from the Timestamp object directly
  (via __getattr__()). Other properties and methods are also passed through
  but only if we have a datetime year (to be sure).
- All so-called rich comparison methods ar implemented to compare WbType
  instances
- Reworking of the toTimestr() which is a modification of isoformat
- Rewrite of the precision autodetection which only checks the first valid
  occurance of the time parameter instead of overwriting the assignmet over
  and over again. This may be a breaking change because the precision is
  defined by the lowest valid value except of the highest invalid value.
- Assign the default values to the Timestamp constructor. There is no need
  to hold it locally or as instance variable.
- Change doc string to keep lines beneath 80 chars.
- Remove unneeded FORMATSTR class constant.
- A lot of tests added.

Bug: T148280
Change-Id: If25b71e9d0fd04634a8bfaa783598e48d4226209
---
M pywikibot/__init__.py
M tests/wikibase_tests.py
2 files changed, 133 insertions(+), 48 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core 
refs/changes/20/316220/1

diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 37f03bb..14ad924 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -416,8 +416,6 @@
                  'second': 14
                  }
 
-    FORMATSTR = '{0:+012d}-{1:02d}-{2:02d}T{3:02d}:{4:02d}:{5:02d}Z'
-
     _items = ('year', 'month', 'day', 'hour', 'minute', 'second',
               'precision', 'before', 'after', 'timezone', 'calendarmodel')
 
@@ -432,11 +430,15 @@
         readable string, e.g., 'hour'. If no precision is given, it is set
         according to the given time units.
 
-        Timezone information is given in three different ways depending on the 
time:
-        * Times after the implementation of UTC (1972): as an offset from UTC 
in minutes;
-        * Times before the implementation of UTC: the offset of the time zone 
from universal time;
-        * Before the implementation of time zones: The longitude of the place 
of
-          the event, in the range −180° to 180°, multiplied by 4 to convert to 
minutes.
+        Timezone information is given in three different ways depending on the
+        time:
+        * Times after the implementation of UTC (1972): as an offset from UTC
+          in minutes;
+        * Times before the implementation of UTC: the offset of the time zone
+          from universal time;
+        * Before the implementation of time zones: The longitude of the place
+          of the event, in the range −180° to 180°, multiplied by 4 to convert
+          to minutes.
 
         @param year: The year as a signed integer of between 1 and 16 digits.
         @type year: long
@@ -452,11 +454,11 @@
         @type second: int
         @param precision: The unit of the precision of the time.
         @type precision: int or str
-        @param before: Number of units after the given time it could be, if 
uncertain.
-            The unit is given by the precision.
+        @param before: Number of units after the given time it could be,
+            if uncertain. The unit is given by the precision.
         @type before: int
-        @param after: Number of units before the given time it could be, if 
uncertain.
-            The unit is given by the precision.
+        @param after: Number of units before the given time it could be,
+            if uncertain. The unit is given by the precision.
         @type after: int
         @param timezone: Timezone information in minutes.
         @type timezone: int
@@ -467,37 +469,6 @@
         """
         if year is None:
             raise ValueError('no year given')
-        self.precision = self.PRECISION['second']
-        if second is None:
-            self.precision = self.PRECISION['minute']
-            second = 0
-        if minute is None:
-            self.precision = self.PRECISION['hour']
-            minute = 0
-        if hour is None:
-            self.precision = self.PRECISION['day']
-            hour = 0
-        if day is None:
-            self.precision = self.PRECISION['month']
-            day = 1
-        if month is None:
-            self.precision = self.PRECISION['year']
-            month = 1
-        self.year = long(year)
-        self.month = month
-        self.day = day
-        self.hour = hour
-        self.minute = minute
-        self.second = second
-        self.after = after
-        self.before = before
-        self.timezone = timezone
-        if calendarmodel is None:
-            if site is None:
-                site = Site().data_repository()
-            calendarmodel = site.calendarmodel()
-        self.calendarmodel = calendarmodel
-
         # if precision is given it overwrites the autodetection above
         if precision is not None:
             if (isinstance(precision, int) and
@@ -507,6 +478,94 @@
                 self.precision = self.PRECISION[precision]
             else:
                 raise ValueError('Invalid precision: "%s"' % precision)
+        # autodetection
+        elif second is not None:
+            self.precision = self.PRECISION['second']
+        elif minute is not None:
+            self.precision = self.PRECISION['minute']
+        elif hour is not None:
+            self.precision = self.PRECISION['hour']
+        elif day is not None:
+            self.precision = self.PRECISION['day']
+        elif month is not None:
+            self.precision = self.PRECISION['month']
+        else:
+            self.precision = self.PRECISION['year']
+        self.after = after
+        self.before = before
+        self.timezone = timezone
+        if calendarmodel is None:
+            if site is None:
+                site = Site().data_repository()
+            calendarmodel = site.calendarmodel()
+        self.calendarmodel = calendarmodel
+
+        if year < datetime.MINYEAR or year > datetime.MAXYEAR:
+            self._year = long(year)
+            year = 2000
+        else:
+            self._year = 0
+        self._timestamp = Timestamp(year, month or 1, day or 1, hour or 0,
+                                    minute or 0, second or 0)
+
+    def __lt__(self, other):
+        """Compare if self is less than other."""
+        return self._year < other._year or (
+            self._year == other._year and self._timestamp < other._timestamp)
+
+    def __le__(self, other):
+        """Compare if self is less equals other."""
+        return self._year < other._year or (
+            self._year == other._year and self._timestamp <= other._timestamp)
+
+    def __eq__(self, other):
+        """Compare if self is equal to other."""
+        return self._year == other._year and self._timestamp == 
other._timestamp
+
+    def __ne__(self, other):
+        """Compare if self is not equal to other."""
+        return not self.__eq__(other)
+
+    def __gt__(self, other):
+        """Compare if self is greater than other."""
+        return self._year > other._year or (
+            self._year == other._year and self._timestamp > other._timestamp)
+
+    def __ge__(self, other):
+        """Compare if self is greater equals other."""
+        return self._year > other._year or (
+            self._year == other._year and self._timestamp >= other._timestamp)
+
+    def __getattr__(self, name):
+        """Provide time parts from Timestamp."""
+        if self.is_datetime_year() and hasattr(
+                self._timestamp, name) or name in self._items[:6]:
+            return getattr(self._timestamp, name)
+        raise AttributeError(
+            "{0} object has no attribute '{1}'".format(self.__class__.__name__,
+                                                       name))
+
+    @property
+    def year(self):
+        """Return the year of the WbTime."""
+        return long(self._year or self._timestamp.year)
+
+    def is_datetime_year(self):
+        """Check whether year is in datetime range MINYEAR to MAXYEAR."""
+        return self._year == 0
+
+    def toTimestamp(self):
+        """
+        Convert data to Timestamp.
+
+        @return: timestamp of WbTime time
+        @rtype: Timestamp
+        @raises ValueError: When year is outsite datetime year range
+        """
+        if not self.is_datetime_year():
+            raise ValueError(
+                'Year {0} is out of Timestamp range'.format(self._year))
+        return self._timestamp
 
     @classmethod
     def fromTimestr(cls, datetimestr, precision=14, before=0, after=0,
@@ -554,8 +613,8 @@
         @return: Timestamp in a format resembling ISO 8601
         @rtype: str
         """
-        return self.FORMATSTR.format(self.year, self.month, self.day,
-                                     self.hour, self.minute, self.second)
+        return '{0:+012d}-{1}'.format(self.year,
+                                      self._timestamp.isoformat()[5:])
 
     def toWikibase(self):
         """
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index f428475..a0d63c1 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8  -*-
 """Tests for the Wikidata parts of the page module."""
 #
-# (C) Pywikibot team, 2008-2014
+# (C) Pywikibot team, 2008-2016
 #
 # Distributed under the terms of the MIT license.
 #
@@ -160,10 +160,36 @@
     def test_WbTime(self):
         """Test WbTime."""
         repo = self.get_repo()
-        t = pywikibot.WbTime(site=repo, year=2010, hour=12, minute=43)
-        self.assertEqual(t.toTimestr(), '+00000002010-01-01T12:43:00Z')
+        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.assertTrue(t1.is_datetime_year())
+        self.assertFalse(t2.is_datetime_year())
+        self.assertEqual(t1.toTimestr(), '+00000002010-01-01T12:43:00Z')
+        self.assertEqual(t2.toTimestr(), '-00000002005-01-01T16:45:00Z')
+        self.assertEqual(t1.totimestampformat(), '20100101124300')
+        self.assertFalse(hasattr(t2, 'totimestampformat'))
         self.assertRaises(ValueError, pywikibot.WbTime, site=repo, 
precision=15)
-        self.assertRaises(ValueError, pywikibot.WbTime, site=repo, 
precision='invalid_precision')
+        self.assertRaises(ValueError, pywikibot.WbTime, site=repo,
+                          precision='invalid_precision')
+        self.assertIsInstance(t1.toTimestamp(), pywikibot.Timestamp)
+        self.assertRaises(ValueError, t2.toTimestamp)
 
     def test_WbQuantity_integer(self):
         """Test WbQuantity for integer value."""

-- 
To view, visit https://gerrit.wikimedia.org/r/316220
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If25b71e9d0fd04634a8bfaa783598e48d4226209
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Xqt <i...@gno.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to