Closes #27661: Added tzinfo keyword argument to datetime.combine.
This commit is contained in:
parent
711120d8fd
commit
43746c3770
|
@ -794,16 +794,23 @@ Other constructors, all class methods:
|
||||||
microsecond of the result are all 0, and :attr:`.tzinfo` is ``None``.
|
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
|
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`
|
given :class:`date` object's, and whose time components
|
||||||
attributes are equal to the given :class:`.time` object's. For any
|
are equal to the given :class:`.time` object's. If the *tzinfo*
|
||||||
:class:`.datetime` object *d*,
|
argument is provided, its value is used to set the :attr:`.tzinfo` attribute
|
||||||
``d == datetime.combine(d.date(), d.timetz())``. If date is a
|
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
|
:class:`.datetime` object, its time components and :attr:`.tzinfo` attributes
|
||||||
are ignored.
|
are ignored.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added the *tzinfo* argument.
|
||||||
|
|
||||||
|
|
||||||
.. classmethod:: datetime.strptime(date_string, format)
|
.. classmethod:: datetime.strptime(date_string, format)
|
||||||
|
|
||||||
|
|
|
@ -1479,15 +1479,17 @@ class datetime(date):
|
||||||
return cls.utcfromtimestamp(t)
|
return cls.utcfromtimestamp(t)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def combine(cls, date, time):
|
def combine(cls, date, time, tzinfo=True):
|
||||||
"Construct a datetime from a given date and a given time."
|
"Construct a datetime from a given date and a given time."
|
||||||
if not isinstance(date, _date_class):
|
if not isinstance(date, _date_class):
|
||||||
raise TypeError("date argument must be a date instance")
|
raise TypeError("date argument must be a date instance")
|
||||||
if not isinstance(time, _time_class):
|
if not isinstance(time, _time_class):
|
||||||
raise TypeError("time argument must be a time instance")
|
raise TypeError("time argument must be a time instance")
|
||||||
|
if tzinfo is True:
|
||||||
|
tzinfo = time.tzinfo
|
||||||
return cls(date.year, date.month, date.day,
|
return cls(date.year, date.month, date.day,
|
||||||
time.hour, time.minute, time.second, time.microsecond,
|
time.hour, time.minute, time.second, time.microsecond,
|
||||||
time.tzinfo, fold=time.fold)
|
tzinfo, fold=time.fold)
|
||||||
|
|
||||||
def timetuple(self):
|
def timetuple(self):
|
||||||
"Return local time tuple compatible with time.localtime()."
|
"Return local time tuple compatible with time.localtime()."
|
||||||
|
|
|
@ -2117,11 +2117,22 @@ class TestDateTime(TestDate):
|
||||||
self.assertRaises(TypeError, combine) # need an arg
|
self.assertRaises(TypeError, combine) # need an arg
|
||||||
self.assertRaises(TypeError, combine, d) # need two args
|
self.assertRaises(TypeError, combine, d) # need two args
|
||||||
self.assertRaises(TypeError, combine, t, d) # args reversed
|
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, "date", "time") # wrong types
|
||||||
self.assertRaises(TypeError, combine, d, "time") # wrong type
|
self.assertRaises(TypeError, combine, d, "time") # wrong type
|
||||||
self.assertRaises(TypeError, combine, "date", t) # 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):
|
def test_replace(self):
|
||||||
cls = self.theclass
|
cls = self.theclass
|
||||||
args = [1, 2, 3, 4, 5, 6, 7]
|
args = [1, 2, 3, 4, 5, 6, 7]
|
||||||
|
|
|
@ -40,6 +40,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #27661: Added tzinfo keyword argument to datetime.combine.
|
||||||
|
|
||||||
- Issue #27568: Prevent HTTPoxy attack (CVE-2016-1000110). Ignore the
|
- Issue #27568: Prevent HTTPoxy attack (CVE-2016-1000110). Ignore the
|
||||||
HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates
|
HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates
|
||||||
that the script is in CGI mode.
|
that the script is in CGI mode.
|
||||||
|
|
|
@ -4430,18 +4430,21 @@ datetime_strptime(PyObject *cls, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
|
datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
|
||||||
{
|
{
|
||||||
static char *keywords[] = {"date", "time", NULL};
|
static char *keywords[] = {"date", "time", "tzinfo", NULL};
|
||||||
PyObject *date;
|
PyObject *date;
|
||||||
PyObject *time;
|
PyObject *time;
|
||||||
|
PyObject *tzinfo = NULL;
|
||||||
PyObject *result = 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_DateType, &date,
|
||||||
&PyDateTime_TimeType, &time)) {
|
&PyDateTime_TimeType, &time, &tzinfo)) {
|
||||||
PyObject *tzinfo = Py_None;
|
if (tzinfo == NULL) {
|
||||||
|
|
||||||
if (HASTZINFO(time))
|
if (HASTZINFO(time))
|
||||||
tzinfo = ((PyDateTime_Time *)time)->tzinfo;
|
tzinfo = ((PyDateTime_Time *)time)->tzinfo;
|
||||||
|
else
|
||||||
|
tzinfo = Py_None;
|
||||||
|
}
|
||||||
result = PyObject_CallFunction(cls, "iiiiiiiO",
|
result = PyObject_CallFunction(cls, "iiiiiiiO",
|
||||||
GET_YEAR(date),
|
GET_YEAR(date),
|
||||||
GET_MONTH(date),
|
GET_MONTH(date),
|
||||||
|
@ -4451,6 +4454,7 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
|
||||||
TIME_GET_SECOND(time),
|
TIME_GET_SECOND(time),
|
||||||
TIME_GET_MICROSECOND(time),
|
TIME_GET_MICROSECOND(time),
|
||||||
tzinfo);
|
tzinfo);
|
||||||
|
if (result)
|
||||||
DATE_SET_FOLD(result, TIME_GET_FOLD(time));
|
DATE_SET_FOLD(result, TIME_GET_FOLD(time));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue