diff --git a/docs/changes/4.0.0.rst b/docs/changes/4.0.0.rst index 757b43baa..3b3202f66 100644 --- a/docs/changes/4.0.0.rst +++ b/docs/changes/4.0.0.rst @@ -226,7 +226,13 @@ Breaking Changes :class:`~falcon.HTTPStatus` classes were removed. (`#2090 `__) - The function :func:`falcon.http_date_to_dt` now validates HTTP dates to have the correct timezone set. It now also returns timezone-aware - :class:`~datetime.datetime` objects. (`#2182 `__) + :class:`~datetime.datetime` objects. As a consequence of this change, the + return value of :meth:`falcon.Request.get_header_as_datetime` (including the + derived properties :attr:`~falcon.Request.date`, + :attr:`~falcon.Request.if_modified_since`, + :attr:`~falcon.Request.if_unmodified_since`, and + :attr:`falcon.testing.Cookie.expires`) has also changed to timezone-aware. + (`#2182 `__) - ``setup.cfg`` was dropped in favor of consolidating all static project configuration in ``pyproject.toml`` (``setup.py`` is still needed for programmatic control of the build process). While this change should not impact diff --git a/falcon/request.py b/falcon/request.py index a3f690e1b..c95c743d5 100644 --- a/falcon/request.py +++ b/falcon/request.py @@ -472,6 +472,10 @@ def date(self) -> Optional[datetime]: """Value of the Date header, converted to a ``datetime`` instance. The header value is assumed to conform to RFC 1123. + + .. versionchanged:: 4.0 + This property now returns timezone-aware + :class:`~datetime.datetime` objects (or ``None``). """ return self.get_header_as_datetime('Date') @@ -525,6 +529,10 @@ def if_modified_since(self) -> Optional[datetime]: """Value of the If-Modified-Since header. Returns ``None`` if the header is missing. + + .. versionchanged:: 4.0 + This property now returns timezone-aware + :class:`~datetime.datetime` objects (or ``None``). """ return self.get_header_as_datetime('If-Modified-Since') @@ -533,6 +541,10 @@ def if_unmodified_since(self) -> Optional[datetime]: """Value of the If-Unmodified-Since header. Returns ``None`` if the header is missing. + + .. versionchanged:: 4.0 + This property now returns timezone-aware + :class:`~datetime.datetime` objects (or ``None``). """ return self.get_header_as_datetime('If-Unmodified-Since') @@ -1331,6 +1343,10 @@ def get_header_as_datetime( HTTPBadRequest: The header was not found in the request, but it was required. HttpInvalidHeader: The header contained a malformed/invalid value. + + .. versionchanged:: 4.0 + This method now returns timezone-aware :class:`~datetime.datetime` + objects. """ http_date = self.get_header(header, required=required) diff --git a/falcon/testing/client.py b/falcon/testing/client.py index e1f14959f..77a16bf7e 100644 --- a/falcon/testing/client.py +++ b/falcon/testing/client.py @@ -151,7 +151,12 @@ def value(self) -> str: @property def expires(self) -> Optional[dt.datetime]: - """Expiration timestamp for the cookie, or ``None`` if not specified.""" + """Expiration timestamp for the cookie, or ``None`` if not specified. + + .. versionchanged:: 4.0 + This property now returns timezone-aware + :class:`~datetime.datetime` objects (or ``None``). + """ if self._expires: return http_date_to_dt(self._expires, obs_date=True) diff --git a/falcon/util/misc.py b/falcon/util/misc.py index 1f68626ca..ae17c12a1 100644 --- a/falcon/util/misc.py +++ b/falcon/util/misc.py @@ -174,6 +174,10 @@ def http_date_to_dt(http_date: str, obs_date: bool = False) -> datetime.datetime Raises: ValueError: http_date doesn't match any of the available time formats ValueError: http_date doesn't match allowed timezones + + .. versionchanged:: 4.0 + This function now returns timezone-aware :class:`~datetime.datetime` + objects. """ if not obs_date: # PERF(kgriffs): This violates DRY, but we do it anyway