summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZackery Spytz <zspytz@gmail.com>2020-09-23 18:43:45 (GMT)
committerGitHub <noreply@github.com>2020-09-23 18:43:45 (GMT)
commit2e4dd336e5b50fd30947fdecb605ddcd71f7f6f5 (patch)
tree7b8e1b98c94d77ffcdcfc61645c6b40f5ebd44ab
parent9c4eac7f02ddcf32fc1cdaf7c08c37fe9718c1fb (diff)
downloadcpython-2e4dd336e5b50fd30947fdecb605ddcd71f7f6f5.zip
cpython-2e4dd336e5b50fd30947fdecb605ddcd71f7f6f5.tar.gz
cpython-2e4dd336e5b50fd30947fdecb605ddcd71f7f6f5.tar.bz2
bpo-30155: Add macros to get tzinfo from datetime instances (GH-21633)
Add PyDateTime_DATE_GET_TZINFO() and PyDateTime_TIME_GET_TZINFO() macros.
-rw-r--r--Doc/c-api/datetime.rst11
-rw-r--r--Doc/whatsnew/3.10.rst6
-rw-r--r--Include/datetime.h8
-rw-r--r--Lib/test/datetimetester.py14
-rw-r--r--Misc/NEWS.d/next/C API/2020-07-26-19-39-45.bpo-30155.rHZRJ_.rst3
-rw-r--r--Modules/_datetimemodule.c11
-rw-r--r--Modules/_testcapimodule.c6
-rw-r--r--Modules/_zoneinfo.c4
8 files changed, 46 insertions, 17 deletions
diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst
index bd4f1ff..415ce4c 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 606fad2..1228f26 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 5d9f255..bb56520 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 520a51d..8b61c26 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -5991,30 +5991,36 @@ class CapiTest(unittest.TestCase):
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 0000000..a276759
--- /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 74a54e7..0631272 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 7536d29..0e09877 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 2cee65f..bee59b8 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)