diff --git a/Lib/datetime.py b/Lib/datetime.py index 9f942a207e8..36374aa94c8 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -288,7 +288,7 @@ def _check_date_fields(year, month, day): raise ValueError('day must be in 1..%d' % dim, day) return year, month, day -def _check_time_fields(hour, minute, second, microsecond): +def _check_time_fields(hour, minute, second, microsecond, fold): hour = _check_int_field(hour) minute = _check_int_field(minute) second = _check_int_field(second) @@ -301,7 +301,9 @@ def _check_time_fields(hour, minute, second, microsecond): raise ValueError('second must be in 0..59', second) if not 0 <= microsecond <= 999999: raise ValueError('microsecond must be in 0..999999', microsecond) - return hour, minute, second, microsecond + if fold not in (0, 1): + raise ValueError('fold must be either 0 or 1', fold) + return hour, minute, second, microsecond, fold def _check_tzinfo_arg(tz): if tz is not None and not isinstance(tz, tzinfo): @@ -1059,8 +1061,8 @@ class time: self.__setstate(hour, minute or None) self._hashcode = -1 return self - hour, minute, second, microsecond = _check_time_fields( - hour, minute, second, microsecond) + hour, minute, second, microsecond, fold = _check_time_fields( + hour, minute, second, microsecond, fold) _check_tzinfo_arg(tzinfo) self = object.__new__(cls) self._hour = hour @@ -1369,8 +1371,8 @@ class datetime(date): self._hashcode = -1 return self year, month, day = _check_date_fields(year, month, day) - hour, minute, second, microsecond = _check_time_fields( - hour, minute, second, microsecond) + hour, minute, second, microsecond, fold = _check_time_fields( + hour, minute, second, microsecond, fold) _check_tzinfo_arg(tzinfo) self = object.__new__(cls) self._year = year diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index e71f3aa9b46..726b7fde10a 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1724,6 +1724,11 @@ class TestDateTime(TestDate): self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 59, 1000000) + # bad fold + self.assertRaises(ValueError, self.theclass, + 2000, 1, 31, fold=-1) + self.assertRaises(ValueError, self.theclass, + 2000, 1, 31, fold=2) # Positional fold: self.assertRaises(TypeError, self.theclass, 2000, 1, 31, 23, 59, 59, 0, None, 1) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 3048762034e..a62f5929578 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -427,7 +427,7 @@ check_date_args(int year, int month, int day) * aren't, raise ValueError and return -1. */ static int -check_time_args(int h, int m, int s, int us) +check_time_args(int h, int m, int s, int us, int fold) { if (h < 0 || h > 23) { PyErr_SetString(PyExc_ValueError, @@ -449,6 +449,11 @@ check_time_args(int h, int m, int s, int us) "microsecond must be in 0..999999"); return -1; } + if (fold != 0 && fold != 1) { + PyErr_SetString(PyExc_ValueError, + "fold must be either 0 or 1"); + return -1; + } return 0; } @@ -3598,7 +3603,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i", time_kws, &hour, &minute, &second, &usecond, &tzinfo, &fold)) { - if (check_time_args(hour, minute, second, usecond) < 0) + if (check_time_args(hour, minute, second, usecond, fold) < 0) return NULL; if (check_tzinfo_subclass(tzinfo) < 0) return NULL; @@ -3926,8 +3931,14 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) if (tuple == NULL) return NULL; clone = time_new(Py_TYPE(self), tuple, NULL); - if (clone != NULL) + if (clone != NULL) { + if (fold != 0 && fold != 1) { + PyErr_SetString(PyExc_ValueError, + "fold must be either 0 or 1"); + return NULL; + } TIME_SET_FOLD(clone, fold); + } Py_DECREF(tuple); return clone; } @@ -4175,7 +4186,7 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) &second, &usecond, &tzinfo, &fold)) { if (check_date_args(year, month, day) < 0) return NULL; - if (check_time_args(hour, minute, second, usecond) < 0) + if (check_time_args(hour, minute, second, usecond, fold) < 0) return NULL; if (check_tzinfo_subclass(tzinfo) < 0) return NULL; @@ -5006,8 +5017,15 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) if (tuple == NULL) return NULL; clone = datetime_new(Py_TYPE(self), tuple, NULL); - if (clone != NULL) + + if (clone != NULL) { + if (fold != 0 && fold != 1) { + PyErr_SetString(PyExc_ValueError, + "fold must be either 0 or 1"); + return NULL; + } DATE_SET_FOLD(clone, fold); + } Py_DECREF(tuple); return clone; }