Xqt has submitted this change. (
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1348787?usp=email )
Change subject: time: add timespec to Timestamp.isoformat() method
......................................................................
time: add timespec to Timestamp.isoformat() method
* add the timespec parameter to Timestamp.isoformat(), which was
introduced in Python 3.6
* return the timezone offset specified by the datetime/Timestamp instead
of always returning UTC, while still using 'Z' for a zero offset
* remove the _ISO8601Format classmethod, which is no longer used
* update WbTime.fromTimestamp and use timetuple() directly
* update tests and documentation
Bug: T440120
Bug: T439983
Change-Id: I6e2d6900623157776d4b89efb3de319256200393
---
M docs/api_ref/date_time.rst
M pywikibot/_wbtypes.py
M pywikibot/data/api/_requests.py
M pywikibot/time.py
M tests/time_tests.py
5 files changed, 84 insertions(+), 28 deletions(-)
Approvals:
Xqt: Verified; Looks good to me, approved
Mahveotm: Looks good to me, but someone else must approve
diff --git a/docs/api_ref/date_time.rst b/docs/api_ref/date_time.rst
index f6c65d8..e601115 100644
--- a/docs/api_ref/date_time.rst
+++ b/docs/api_ref/date_time.rst
@@ -3,6 +3,7 @@
******************************************
.. automodule:: pywikibot.time
+ :exclude-members: Timestamp
.. admonition:: Imports in :mod:`pywikibot` module
:class: note
@@ -11,3 +12,6 @@
can also be used as :mod:`pywikibot` members:
- :class:`pywikibot.Timestamp<pywikibot.time.Timestamp>`
+
+.. autoclass:: pywikibot.time.Timestamp
+ :special-members: __repr__, __str__
diff --git a/pywikibot/_wbtypes.py b/pywikibot/_wbtypes.py
index ec882a7..9efd083 100644
--- a/pywikibot/_wbtypes.py
+++ b/pywikibot/_wbtypes.py
@@ -737,9 +737,15 @@
"""
if not timezone and timestamp.tzinfo and copy_timezone:
timezone = int(timestamp.utcoffset().total_seconds() / 60)
- return cls.fromTimestr(timestamp.isoformat(), precision=precision,
- before=before, after=after, timezone=timezone,
- calendarmodel=calendarmodel, site=site)
+ return cls(
+ *timestamp.timetuple()[:6],
+ precision=precision,
+ before=before,
+ after=after,
+ timezone=timezone,
+ calendarmodel=calendarmodel,
+ site=site,
+ )
@staticmethod
def _normalize_millennium(year: int) -> int:
diff --git a/pywikibot/data/api/_requests.py b/pywikibot/data/api/_requests.py
index 254e8c2..4b080c0 100644
--- a/pywikibot/data/api/_requests.py
+++ b/pywikibot/data/api/_requests.py
@@ -350,13 +350,13 @@
Converts from Python datatypes to MediaWiki API parameter values.
Supports:
- * datetime.datetime (using strftime and ISO8601 format)
+ * datetime.datetime/Timestamp (using isoformat method)
* pywikibot.page.BasePage (using title (+namespace; -section))
All other datatypes are converted to string.
"""
if isinstance(value, datetime.datetime):
- return value.strftime(pywikibot.Timestamp.ISO8601Format)
+ return value.isoformat()
if isinstance(value, pywikibot.page.BasePage):
if value.site != self.site:
raise RuntimeError(f'value.site {value.site!r} is different '
diff --git a/pywikibot/time.py b/pywikibot/time.py
index 3f970f8..067d7e1 100644
--- a/pywikibot/time.py
+++ b/pywikibot/time.py
@@ -17,7 +17,7 @@
from contextlib import suppress
import pywikibot
-from pywikibot.tools import PYTHON_VERSION, classproperty
+from pywikibot.tools import PYTHON_VERSION, classproperty, deprecated
__all__ = (
@@ -25,7 +25,8 @@
'str2timedelta',
'MW_KEYS',
'Timestamp',
- 'TZoneFixedOffset'
+ 'TZoneFixedOffset',
+ 'UTC',
)
#: .. version-added:: 7.5
@@ -38,6 +39,13 @@
# 'months' and 'minutes' were removed because confusion outweighs merit
})
+UTC = datetime.timezone.utc
+"""Alias for the UTC time zone singleton :attr:`datetime.timezone.utc`.
+
+.. note:: :attr:`datetime.UTC` is an alias for it since Python 3.11.
+.. version-added:: 11.9
+"""
+
class Timestamp(datetime.datetime):
@@ -217,20 +225,13 @@
raise ValueError(f'time data {timestr!r} does not match any format.')
@classproperty
+ @deprecated(since='11.9.0')
def ISO8601Format(cls) -> str: # noqa: N802
- """ISO8601 format string class property for compatibility purpose."""
- return cls._ISO8601Format()
+ """ISO8601 format string class property for compatibility purpose.
- @classmethod
- def _ISO8601Format(cls, sep: str = 'T') -> str: # noqa: N802
- """ISO8601 format string.
-
- :param sep: One-character separator, placed between the date and
- time
- :return: ISO8601 format string
+ .. version-deprecated:: 11.9
"""
- assert len(sep) == 1
- return f'%Y-%m-%d{sep}%H:%M:%SZ'
+ return '%Y-%m-%dT%H:%M:%SZ'
@classmethod
def fromISOformat(cls, # noqa: N802
@@ -301,14 +302,49 @@
ts += '000000'
return cls._from_mw(ts)
- def isoformat(self, sep: str = 'T') -> str: # type: ignore[override]
- """Convert object to an ISO 8601 timestamp accepted by MediaWiki.
+ def isoformat(self, sep: str = 'T', timespec: str = 'seconds') -> str:
+ """Return a string representing the date and time in ISO 8601 format.
- datetime.datetime.isoformat does not postfix the ISO formatted
- date with a 'Z' unless a timezone is included, which causes
- MediaWiki ~1.19 and earlier to fail.
+ Unlike :meth:`datetime.datetime.isoformat`, this method appends
+ a 'Z' to naive timestamps and uses 'Z' instead of '+00:00' for
+ timestamps with a zero UTC offset. For other timezone offsets,
+ the offset specified by the timestamp is preserved. The default
+ *timespec* is 'seconds' rather than 'auto'.
+
+ **Example:**
+
+ >>> from pywikibot.time import Timestamp, TZoneFixedOffset
+ >>> Timestamp(2026, 10, 4, 11, 22, 8, 132263).isoformat()
+ '2026-10-04T11:22:08Z'
+ >>> Timestamp(2026, 10, 4, 11, 22, 8, tzinfo=UTC).isoformat()
+ '2026-10-04T11:22:08Z'
+ >>> tzo = TZoneFixedOffset(-399, 'UTC')
+ >>> Timestamp(2026, 10, 4, tzinfo=tzo).isoformat(' ')
+ '2026-10-04 00:00:00-06:39'
+ >>> ts = Timestamp(2026, 10, 4, microsecond=100, tzinfo=tzo)
+ >>> ts.isoformat()
+ '2026-10-04T00:00:00-06:39'
+ >>> ts.isoformat(timespec='auto')
+ '2026-10-04T00:00:00.000100-06:39'
+
+ .. version-changed:: 3.0.20171212
+ *sep* parameter was added.
+ .. version-changed:: 11.9
+ *timespec* parameter was added. Timezone offsets are now
+ preserved.
+
+ :param sep: A one-character separator, placed between the date
+ and time portions of the result.
+ :param timespec: specifies the number of additional components
+ of the time to include. Refer :pylib:`datetime.isoformat
+ <datetime#datetime.datetime.isoformat>` for valid values.
"""
- return self.strftime(self._ISO8601Format(sep))
+ ts = super().isoformat(sep, timespec)
+ if self.utcoffset() is None:
+ ts += 'Z'
+ elif self.utcoffset() == datetime.timedelta():
+ ts = ts.replace('+00:00', 'Z')
+ return ts
def totimestampformat(self) -> str:
"""Convert object to a MediaWiki internal timestamp."""
@@ -339,7 +375,13 @@
return f'{type(self).__name__}{s[s.find("("):]}'
def __str__(self) -> str:
- """Return a string format recognized by the API."""
+ """Return a string format recognized by the API.
+
+ For a :class:`Timestamp` instance ``t``, ``str(t)`` is
+ equivalent to :meth:`t.isoformat()<isoformat>`, which includes
+ the 'T' separator unlike the :meth:`datetime.datetime`
+ equivalent.
+ """
return self.isoformat()
@classmethod
diff --git a/tests/time_tests.py b/tests/time_tests.py
index 0a90bef..a1e3c53 100755
--- a/tests/time_tests.py
+++ b/tests/time_tests.py
@@ -14,6 +14,7 @@
from datetime import datetime, timedelta, timezone
from pywikibot.time import Timestamp, parse_duration, str2timedelta
+from pywikibot.tools import suppress_warnings
from tests.aspects import TestCase
@@ -179,9 +180,12 @@
def test_iso_format_property(self) -> None:
"""Test iso format properties."""
- self.assertEqual(Timestamp.ISO8601Format, Timestamp._ISO8601Format())
- self.assertEqual(re.sub(r'[\-:TZ]', '', Timestamp.ISO8601Format),
- Timestamp.mediawikiTSFormat)
+ with suppress_warnings(
+ r'.+Timestamp\.ISO8601Format is deprecated since release 11\.9\.0',
+ category=RuntimeWarning
+ ):
+ self.assertEqual(re.sub(r'[\-:TZ]', '', Timestamp.ISO8601Format),
+ Timestamp.mediawikiTSFormat)
def test_mediawiki_format(self) -> None:
"""Test conversion from and to Timestamp format."""
--
To view, visit
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1348787?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.wikimedia.org/r/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I6e2d6900623157776d4b89efb3de319256200393
Gerrit-Change-Number: 1348787
Gerrit-PatchSet: 6
Gerrit-Owner: Xqt <[email protected]>
Gerrit-Reviewer: Mahveotm <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]