[Python-checkins] cpython: Closes #27661: Added tzinfo keyword argument to datetime.combine.

alexander.belopolsky python-checkins at python.org
Tue Aug 2 17:49:33 EDT 2016


https://hg.python.org/cpython/rev/adce94a718e3
changeset:   102509:adce94a718e3
user:        Alexander Belopolsky <alexander.belopolsky at gmail.com>
date:        Tue Aug 02 17:49:30 2016 -0400
summary:
  Closes #27661: Added tzinfo keyword argument to datetime.combine.

files:
  Doc/library/datetime.rst   |  17 ++++++++---
  Lib/datetime.py            |   6 ++-
  Lib/test/datetimetester.py |  13 ++++++++-
  Misc/NEWS                  |   2 +
  Modules/_datetimemodule.c  |  36 ++++++++++++++-----------
  5 files changed, 50 insertions(+), 24 deletions(-)


diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst
--- a/Doc/library/datetime.rst
+++ b/Doc/library/datetime.rst
@@ -794,16 +794,23 @@
    microsecond of the result are all 0, and :attr:`.tzinfo` is ``None``.
 
 
-.. classmethod:: datetime.combine(date, time)
+.. classmethod:: datetime.combine(date, time[, tzinfo])
 
    Return a new :class:`.datetime` object whose date components are equal to the
-   given :class:`date` object's, and whose time components and :attr:`.tzinfo`
-   attributes are equal to the given :class:`.time` object's. For any
-   :class:`.datetime` object *d*,
-   ``d == datetime.combine(d.date(), d.timetz())``.  If date is a
+   given :class:`date` object's, and whose time components
+   are equal to the given :class:`.time` object's.  If the *tzinfo*
+   argument is provided, its value is used to set the :attr:`.tzinfo` attribute
+   of the result, otherwise the :attr:`~.time.tzinfo` attribute of the *time* argument
+   is used.
+
+   For any :class:`.datetime` object *d*,
+   ``d == datetime.combine(d.date(), d.time(), d.tzinfo)``.  If date is a
    :class:`.datetime` object, its time components and :attr:`.tzinfo` attributes
    are ignored.
 
+   .. versionchanged:: 3.6
+      Added the *tzinfo* argument.
+
 
 .. classmethod:: datetime.strptime(date_string, format)
 
diff --git a/Lib/datetime.py b/Lib/datetime.py
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -1479,15 +1479,17 @@
         return cls.utcfromtimestamp(t)
 
     @classmethod
-    def combine(cls, date, time):
+    def combine(cls, date, time, tzinfo=True):
         "Construct a datetime from a given date and a given time."
         if not isinstance(date, _date_class):
             raise TypeError("date argument must be a date instance")
         if not isinstance(time, _time_class):
             raise TypeError("time argument must be a time instance")
+        if tzinfo is True:
+            tzinfo = time.tzinfo
         return cls(date.year, date.month, date.day,
                    time.hour, time.minute, time.second, time.microsecond,
-                   time.tzinfo, fold=time.fold)
+                   tzinfo, fold=time.fold)
 
     def timetuple(self):
         "Return local time tuple compatible with time.localtime()."
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -2117,11 +2117,22 @@
         self.assertRaises(TypeError, combine) # need an arg
         self.assertRaises(TypeError, combine, d) # need two args
         self.assertRaises(TypeError, combine, t, d) # args reversed
-        self.assertRaises(TypeError, combine, d, t, 1) # too many args
+        self.assertRaises(TypeError, combine, d, t, 1) # wrong tzinfo type
+        self.assertRaises(TypeError, combine, d, t, 1, 2)  # too many args
         self.assertRaises(TypeError, combine, "date", "time") # wrong types
         self.assertRaises(TypeError, combine, d, "time") # wrong type
         self.assertRaises(TypeError, combine, "date", t) # wrong type
 
+        # tzinfo= argument
+        dt = combine(d, t, timezone.utc)
+        self.assertIs(dt.tzinfo, timezone.utc)
+        dt = combine(d, t, tzinfo=timezone.utc)
+        self.assertIs(dt.tzinfo, timezone.utc)
+        t = time()
+        dt = combine(dt, t)
+        self.assertEqual(dt.date(), d)
+        self.assertEqual(dt.time(), t)
+
     def test_replace(self):
         cls = self.theclass
         args = [1, 2, 3, 4, 5, 6, 7]
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -40,6 +40,8 @@
 Library
 -------
 
+- Issue #27661: Added tzinfo keyword argument to datetime.combine.
+
 - Issue #27568: Prevent HTTPoxy attack (CVE-2016-1000110). Ignore the
   HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates
   that the script is in CGI mode.
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -4430,28 +4430,32 @@
 static PyObject *
 datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
 {
-    static char *keywords[] = {"date", "time", NULL};
+    static char *keywords[] = {"date", "time", "tzinfo", NULL};
     PyObject *date;
     PyObject *time;
+    PyObject *tzinfo = NULL;
     PyObject *result = NULL;
 
-    if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
+    if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O:combine", keywords,
                                     &PyDateTime_DateType, &date,
-                                    &PyDateTime_TimeType, &time)) {
-        PyObject *tzinfo = Py_None;
-
-        if (HASTZINFO(time))
-            tzinfo = ((PyDateTime_Time *)time)->tzinfo;
+                                    &PyDateTime_TimeType, &time, &tzinfo)) {
+        if (tzinfo == NULL) {
+            if (HASTZINFO(time))
+                tzinfo = ((PyDateTime_Time *)time)->tzinfo;
+            else
+                tzinfo = Py_None;
+        }
         result = PyObject_CallFunction(cls, "iiiiiiiO",
-                                        GET_YEAR(date),
-                                        GET_MONTH(date),
-                                        GET_DAY(date),
-                                        TIME_GET_HOUR(time),
-                                        TIME_GET_MINUTE(time),
-                                        TIME_GET_SECOND(time),
-                                        TIME_GET_MICROSECOND(time),
-                                        tzinfo);
-        DATE_SET_FOLD(result, TIME_GET_FOLD(time));
+                                       GET_YEAR(date),
+                                       GET_MONTH(date),
+                                       GET_DAY(date),
+                                       TIME_GET_HOUR(time),
+                                       TIME_GET_MINUTE(time),
+                                       TIME_GET_SECOND(time),
+                                       TIME_GET_MICROSECOND(time),
+                                       tzinfo);
+        if (result)
+            DATE_SET_FOLD(result, TIME_GET_FOLD(time));
     }
     return result;
 }

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list