mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
bpo-32403: Faster date and datetime constructors (#4993)
* Add tests for date subclass alternate constructors * Switch over alternate date constructors to fast path * Switch datetime constructors to fastpath, fix bpo-32404 * Add fast path for datetime in date subclass constructor * Set fold in constructor in datetime.combine * Add news entries.
This commit is contained in:
parent
6b5a27975a
commit
9f1b7b93f5
4 changed files with 171 additions and 45 deletions
|
|
@ -847,6 +847,27 @@ new_date_ex(int year, int month, int day, PyTypeObject *type)
|
|||
#define new_date(year, month, day) \
|
||||
new_date_ex(year, month, day, &PyDateTime_DateType)
|
||||
|
||||
// Forward declaration
|
||||
static PyObject * new_datetime_ex(int, int, int, int, int, int, int,
|
||||
PyObject*, PyTypeObject*);
|
||||
|
||||
/* Create date instance with no range checking, or call subclass constructor */
|
||||
static PyObject *
|
||||
new_date_subclass_ex(int year, int month, int day, PyObject *cls) {
|
||||
PyObject *result;
|
||||
// We have "fast path" constructors for two subclasses: date and datetime
|
||||
if ((PyTypeObject *)cls == &PyDateTime_DateType) {
|
||||
result = new_date_ex(year, month, day, (PyTypeObject *)cls);
|
||||
} else if ((PyTypeObject *)cls == &PyDateTime_DateTimeType) {
|
||||
result = new_datetime_ex(year, month, day, 0, 0, 0, 0, Py_None,
|
||||
(PyTypeObject *)cls);
|
||||
} else {
|
||||
result = PyObject_CallFunction(cls, "iii", year, month, day);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Create a datetime instance with no range checking. */
|
||||
static PyObject *
|
||||
new_datetime_ex2(int year, int month, int day, int hour, int minute,
|
||||
|
|
@ -894,6 +915,40 @@ new_datetime_ex(int year, int month, int day, int hour, int minute,
|
|||
new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \
|
||||
&PyDateTime_DateTimeType)
|
||||
|
||||
static PyObject *
|
||||
new_datetime_subclass_fold_ex(int year, int month, int day, int hour, int minute,
|
||||
int second, int usecond, PyObject *tzinfo,
|
||||
int fold, PyObject *cls) {
|
||||
PyObject* dt;
|
||||
if ((PyTypeObject*)cls == &PyDateTime_DateTimeType) {
|
||||
// Use the fast path constructor
|
||||
dt = new_datetime(year, month, day, hour, minute, second, usecond,
|
||||
tzinfo, fold);
|
||||
} else {
|
||||
// Subclass
|
||||
dt = PyObject_CallFunction(cls, "iiiiiiiO",
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
second,
|
||||
usecond,
|
||||
tzinfo);
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
new_datetime_subclass_ex(int year, int month, int day, int hour, int minute,
|
||||
int second, int usecond, PyObject *tzinfo,
|
||||
PyObject *cls) {
|
||||
return new_datetime_subclass_fold_ex(year, month, day, hour, minute,
|
||||
second, usecond, tzinfo, 0,
|
||||
cls);
|
||||
}
|
||||
|
||||
/* Create a time instance with no range checking. */
|
||||
static PyObject *
|
||||
new_time_ex2(int hour, int minute, int second, int usecond,
|
||||
|
|
@ -2743,10 +2798,10 @@ date_local_from_object(PyObject *cls, PyObject *obj)
|
|||
if (_PyTime_localtime(t, &tm) != 0)
|
||||
return NULL;
|
||||
|
||||
return PyObject_CallFunction(cls, "iii",
|
||||
tm.tm_year + 1900,
|
||||
tm.tm_mon + 1,
|
||||
tm.tm_mday);
|
||||
return new_date_subclass_ex(tm.tm_year + 1900,
|
||||
tm.tm_mon + 1,
|
||||
tm.tm_mday,
|
||||
cls);
|
||||
}
|
||||
|
||||
/* Return new date from current time.
|
||||
|
|
@ -2809,8 +2864,7 @@ date_fromordinal(PyObject *cls, PyObject *args)
|
|||
">= 1");
|
||||
else {
|
||||
ord_to_ymd(ordinal, &year, &month, &day);
|
||||
result = PyObject_CallFunction(cls, "iii",
|
||||
year, month, day);
|
||||
result = new_date_subclass_ex(year, month, day, cls);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -2845,14 +2899,7 @@ date_fromisoformat(PyObject *cls, PyObject *dtstr) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *result;
|
||||
if ( (PyTypeObject*)cls == &PyDateTime_DateType ) {
|
||||
result = new_date_ex(year, month, day, (PyTypeObject*)cls);
|
||||
} else {
|
||||
result = PyObject_CallFunction(cls, "iii", year, month, day);
|
||||
}
|
||||
|
||||
return result;
|
||||
return new_date_subclass_ex(year, month, day, cls);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4596,9 +4643,8 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
|
|||
fold = 1;
|
||||
}
|
||||
}
|
||||
return new_datetime_ex2(year, month, day, hour,
|
||||
minute, second, us, tzinfo, fold,
|
||||
(PyTypeObject *)cls);
|
||||
return new_datetime_subclass_fold_ex(year, month, day, hour, minute,
|
||||
second, us, tzinfo, fold, cls);
|
||||
}
|
||||
|
||||
/* Internal helper.
|
||||
|
|
@ -4764,17 +4810,16 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
|
|||
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);
|
||||
if (result)
|
||||
DATE_SET_FOLD(result, TIME_GET_FOLD(time));
|
||||
result = new_datetime_subclass_fold_ex(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,
|
||||
TIME_GET_FOLD(time),
|
||||
cls);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -4832,23 +4877,8 @@ datetime_fromisoformat(PyObject* cls, PyObject *dtstr) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* dt;
|
||||
if ( (PyTypeObject*)cls == &PyDateTime_DateTimeType ) {
|
||||
// Use the fast path constructor
|
||||
dt = new_datetime(year, month, day, hour, minute, second, microsecond,
|
||||
tzinfo, 0);
|
||||
} else {
|
||||
// Subclass
|
||||
dt = PyObject_CallFunction(cls, "iiiiiiiO",
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
second,
|
||||
microsecond,
|
||||
tzinfo);
|
||||
}
|
||||
PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute,
|
||||
second, microsecond, tzinfo, cls);
|
||||
|
||||
Py_DECREF(tzinfo);
|
||||
return dt;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue