remove the ability of datetime.time to be considered false (closes #13936)

This commit is contained in:
Benjamin Peterson 2014-03-20 18:00:35 -05:00
parent 265ae86414
commit ee6bdc07d6
6 changed files with 20 additions and 64 deletions

View File

@ -1378,10 +1378,13 @@ Supported operations:
* efficient pickling
* in Boolean contexts, a :class:`.time` object is considered to be true if and
only if, after converting it to minutes and subtracting :meth:`utcoffset` (or
``0`` if that's ``None``), the result is non-zero.
In boolean contexts, a :class:`.time` object is always considered to be true.
.. versionchanged:: 3.5
Before Python 3.5, a :class:`.time` object was considered to be false if it
represented midnight in UTC. This behavior was considered obscure and
error-prone and has been removed in Python 3.5. See :issue:`13936` for full
details.
Instance methods:

View File

@ -186,4 +186,7 @@ Porting to Python 3.5
This section lists previously described changes and other bugfixes
that may require changes to your code.
* Nothing yet.
* Before Python 3.5, a :class:`datetime.time` object was considered to be false
if it represented midnight in UTC. This behavior was considered obscure and
error-prone and has been removed in Python 3.5. See :issue:`13936` for full
details.

View File

@ -1249,12 +1249,6 @@ class time:
_check_tzinfo_arg(tzinfo)
return time(hour, minute, second, microsecond, tzinfo)
def __bool__(self):
if self.second or self.microsecond:
return True
offset = self.utcoffset() or timedelta(0)
return timedelta(hours=self.hour, minutes=self.minute) != offset
# Pickle support.
def _getstate(self):

View File

@ -2270,13 +2270,14 @@ class TestTime(HarmlessMixedComparison, unittest.TestCase):
self.assertEqual(orig, derived)
def test_bool(self):
# time is always True.
cls = self.theclass
self.assertTrue(cls(1))
self.assertTrue(cls(0, 1))
self.assertTrue(cls(0, 0, 1))
self.assertTrue(cls(0, 0, 0, 1))
self.assertFalse(cls(0))
self.assertFalse(cls())
self.assertTrue(cls(0))
self.assertTrue(cls())
def test_replace(self):
cls = self.theclass
@ -2629,7 +2630,7 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
self.assertEqual(derived.tzname(), 'cookie')
def test_more_bool(self):
# Test cases with non-None tzinfo.
# time is always True.
cls = self.theclass
t = cls(0, tzinfo=FixedOffset(-300, ""))
@ -2639,22 +2640,10 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
self.assertTrue(t)
t = cls(5, tzinfo=FixedOffset(300, ""))
self.assertFalse(t)
t = cls(23, 59, tzinfo=FixedOffset(23*60 + 59, ""))
self.assertFalse(t)
# Mostly ensuring this doesn't overflow internally.
t = cls(0, tzinfo=FixedOffset(23*60 + 59, ""))
self.assertTrue(t)
# But this should yield a value error -- the utcoffset is bogus.
t = cls(0, tzinfo=FixedOffset(24*60, ""))
self.assertRaises(ValueError, lambda: bool(t))
# Likewise.
t = cls(0, tzinfo=FixedOffset(-24*60, ""))
self.assertRaises(ValueError, lambda: bool(t))
t = cls(23, 59, tzinfo=FixedOffset(23*60 + 59, ""))
self.assertTrue(t)
def test_replace(self):
cls = self.theclass

View File

@ -23,6 +23,9 @@ Core and Builtins
Library
-------
- Issue #13936: Remove the ability of datetime.time instances to be considered
false in boolean contexts.
- Issue 18931: selectors module now supports /dev/poll on Solaris.
Patch by Giampaolo Rodola'.

View File

@ -3805,29 +3805,6 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
return clone;
}
static int
time_bool(PyObject *self)
{
PyObject *offset, *tzinfo;
int offsecs = 0;
if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
/* Since utcoffset is in whole minutes, nothing can
* alter the conclusion that this is nonzero.
*/
return 1;
}
tzinfo = GET_TIME_TZINFO(self);
if (tzinfo != Py_None) {
offset = call_utcoffset(tzinfo, Py_None);
if (offset == NULL)
return -1;
offsecs = GET_TD_DAYS(offset)*86400 + GET_TD_SECONDS(offset);
Py_DECREF(offset);
}
return (TIME_GET_MINUTE(self)*60 - offsecs + TIME_GET_HOUR(self)*3600) != 0;
}
/* Pickle support, a simple use of __reduce__. */
/* Let basestate be the non-tzinfo data string.
@ -3895,19 +3872,6 @@ PyDoc_STR("time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time
All arguments are optional. tzinfo may be None, or an instance of\n\
a tzinfo subclass. The remaining arguments may be ints.\n");
static PyNumberMethods time_as_number = {
0, /* nb_add */
0, /* nb_subtract */
0, /* nb_multiply */
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
0, /* nb_negative */
0, /* nb_positive */
0, /* nb_absolute */
(inquiry)time_bool, /* nb_bool */
};
static PyTypeObject PyDateTime_TimeType = {
PyVarObject_HEAD_INIT(NULL, 0)
"datetime.time", /* tp_name */
@ -3919,7 +3883,7 @@ static PyTypeObject PyDateTime_TimeType = {
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc)time_repr, /* tp_repr */
&time_as_number, /* tp_as_number */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)time_hash, /* tp_hash */