diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst index bd4f1ff446bcf4..415ce4cac67f15 100644 --- a/Doc/c-api/datetime.rst +++ b/Doc/c-api/datetime.rst @@ -185,6 +185,11 @@ must not be ``NULL``, and the type is not checked: Return the microsecond, as an int from 0 through 999999. +.. c:function:: PyObject* PyDateTime_DATE_GET_TZINFO(PyDateTime_DateTime *o) + + Return the tzinfo (which may be ``None``). + + .. versionadded:: 3.10 Macros to extract fields from time objects. The argument must be an instance of :c:data:`PyDateTime_Time`, including subclasses. The argument must not be ``NULL``, @@ -209,6 +214,12 @@ and the type is not checked: Return the microsecond, as an int from 0 through 999999. +.. c:function:: PyObject* PyDateTime_TIME_GET_TZINFO(PyDateTime_Time *o) + + Return the tzinfo (which may be ``None``). + + .. versionadded:: 3.10 + Macros to extract fields from time delta objects. The argument must be an instance of :c:data:`PyDateTime_Delta`, including subclasses. The argument must diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 606fad2fdcf059..1228f2695496c5 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -231,6 +231,12 @@ New Features Python executable. (Contributed by Victor Stinner in :issue:`23427`.) +* The :c:func:`PyDateTime_DATE_GET_TZINFO` and + :c:func:`PyDateTime_TIME_GET_TZINFO` macros have been added for accessing + the ``tzinfo`` attributes of :class:`datetime.datetime` and + :class:`datetime.time` objects. + (Contributed by Zackery Spytz in :issue:`30155`.) + Porting to Python 3.10 ---------------------- diff --git a/Include/datetime.h b/Include/datetime.h index 5d9f2558f924d0..bb565201a164d7 100644 --- a/Include/datetime.h +++ b/Include/datetime.h @@ -115,6 +115,10 @@ typedef struct /* Apply for date and datetime instances. */ + +// o is a pointer to a time or a datetime object. +#define _PyDateTime_HAS_TZINFO(o) (((_PyDateTime_BaseTZInfo *)(o))->hastzinfo) + #define PyDateTime_GET_YEAR(o) ((((PyDateTime_Date*)o)->data[0] << 8) | \ ((PyDateTime_Date*)o)->data[1]) #define PyDateTime_GET_MONTH(o) (((PyDateTime_Date*)o)->data[2]) @@ -128,6 +132,8 @@ typedef struct (((PyDateTime_DateTime*)o)->data[8] << 8) | \ ((PyDateTime_DateTime*)o)->data[9]) #define PyDateTime_DATE_GET_FOLD(o) (((PyDateTime_DateTime*)o)->fold) +#define PyDateTime_DATE_GET_TZINFO(o) (_PyDateTime_HAS_TZINFO(o) ? \ + ((PyDateTime_DateTime *)(o))->tzinfo : Py_None) /* Apply for time instances. */ #define PyDateTime_TIME_GET_HOUR(o) (((PyDateTime_Time*)o)->data[0]) @@ -138,6 +144,8 @@ typedef struct (((PyDateTime_Time*)o)->data[4] << 8) | \ ((PyDateTime_Time*)o)->data[5]) #define PyDateTime_TIME_GET_FOLD(o) (((PyDateTime_Time*)o)->fold) +#define PyDateTime_TIME_GET_TZINFO(o) (_PyDateTime_HAS_TZINFO(o) ? \ + ((PyDateTime_Time *)(o))->tzinfo : Py_None) /* Apply for time delta instances */ #define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 520a51df879997..8b61c26f9e5c24 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5991,30 +5991,36 @@ class DateTimeSubclass(datetime): for klass in [datetime, DateTimeSubclass]: for args in [(1993, 8, 26, 22, 12, 55, 99999), - (1993, 8, 26, 22, 12, 55, 99999)]: + (1993, 8, 26, 22, 12, 55, 99999, + timezone.utc)]: d = klass(*args) with self.subTest(cls=klass, date=args): - hour, minute, second, microsecond = _testcapi.PyDateTime_DATE_GET(d) + hour, minute, second, microsecond, tzinfo = \ + _testcapi.PyDateTime_DATE_GET(d) self.assertEqual(hour, d.hour) self.assertEqual(minute, d.minute) self.assertEqual(second, d.second) self.assertEqual(microsecond, d.microsecond) + self.assertIs(tzinfo, d.tzinfo) def test_PyDateTime_TIME_GET(self): class TimeSubclass(time): pass for klass in [time, TimeSubclass]: - for args in [(12, 30, 20, 10), (12, 30, 20, 10)]: + for args in [(12, 30, 20, 10), + (12, 30, 20, 10, timezone.utc)]: d = klass(*args) with self.subTest(cls=klass, date=args): - hour, minute, second, microsecond = _testcapi.PyDateTime_TIME_GET(d) + hour, minute, second, microsecond, tzinfo = \ + _testcapi.PyDateTime_TIME_GET(d) self.assertEqual(hour, d.hour) self.assertEqual(minute, d.minute) self.assertEqual(second, d.second) self.assertEqual(microsecond, d.microsecond) + self.assertIs(tzinfo, d.tzinfo) def test_timezones_offset_zero(self): utc0, utc1, non_utc = _testcapi.get_timezones_offset_zero() diff --git a/Misc/NEWS.d/next/C API/2020-07-26-19-39-45.bpo-30155.rHZRJ_.rst b/Misc/NEWS.d/next/C API/2020-07-26-19-39-45.bpo-30155.rHZRJ_.rst new file mode 100644 index 00000000000000..a276759da79338 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-07-26-19-39-45.bpo-30155.rHZRJ_.rst @@ -0,0 +1,3 @@ +Add :c:func:`PyDateTime_DATE_GET_TZINFO` and +:c:func:`PyDateTime_TIME_GET_TZINFO` macros for accessing the ``tzinfo`` +attributes of :class:`datetime.datetime` and :class:`datetime.time` objects. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 74a54e74ae0fec..0631272429f4f1 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -115,14 +115,9 @@ class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCa #define SET_TD_SECONDS(o, v) ((o)->seconds = (v)) #define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v)) -/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns - * p->hastzinfo. - */ -#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) -#define GET_TIME_TZINFO(p) (HASTZINFO(p) ? \ - ((PyDateTime_Time *)(p))->tzinfo : Py_None) -#define GET_DT_TZINFO(p) (HASTZINFO(p) ? \ - ((PyDateTime_DateTime *)(p))->tzinfo : Py_None) +#define HASTZINFO _PyDateTime_HAS_TZINFO +#define GET_TIME_TZINFO PyDateTime_TIME_GET_TZINFO +#define GET_DT_TZINFO PyDateTime_DATE_GET_TZINFO /* M is a char or int claiming to be a valid month. The macro is equivalent * to the two-sided Python test * 1 <= M <= 12 diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 7536d29535038c..0e098779696b73 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2677,8 +2677,9 @@ test_PyDateTime_DATE_GET(PyObject *self, PyObject *obj) minute = PyDateTime_DATE_GET_MINUTE(obj); second = PyDateTime_DATE_GET_SECOND(obj); microsecond = PyDateTime_DATE_GET_MICROSECOND(obj); + PyObject *tzinfo = PyDateTime_DATE_GET_TZINFO(obj); - return Py_BuildValue("(llll)", hour, minute, second, microsecond); + return Py_BuildValue("(llllO)", hour, minute, second, microsecond, tzinfo); } static PyObject * @@ -2690,8 +2691,9 @@ test_PyDateTime_TIME_GET(PyObject *self, PyObject *obj) minute = PyDateTime_TIME_GET_MINUTE(obj); second = PyDateTime_TIME_GET_SECOND(obj); microsecond = PyDateTime_TIME_GET_MICROSECOND(obj); + PyObject *tzinfo = PyDateTime_TIME_GET_TZINFO(obj); - return Py_BuildValue("(llll)", hour, minute, second, microsecond); + return Py_BuildValue("(llllO)", hour, minute, second, microsecond, tzinfo); } static PyObject * diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index 2cee65fac6dd04..bee59b8d2ae0cc 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -484,9 +484,7 @@ zoneinfo_tzname(PyObject *self, PyObject *dt) return tti->tzname; } -#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) -#define GET_DT_TZINFO(p) \ - (HASTZINFO(p) ? ((PyDateTime_DateTime *)(p))->tzinfo : Py_None) +#define GET_DT_TZINFO PyDateTime_DATE_GET_TZINFO static PyObject * zoneinfo_fromutc(PyObject *obj_self, PyObject *dt)
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: