gh-112919: Speed-up datetime, date and time.replace() (GH-112921)

Use argument clinic and call new_* functions directly. This speeds up
these functions 6x to 7.5x when calling with keyword arguments.
This commit is contained in:
Eugene Toder 2024-01-30 10:19:46 -05:00 committed by GitHub
parent 4287e8608b
commit 1f515e8a10
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 479 additions and 99 deletions

View file

@ -876,6 +876,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(database)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(database));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(day));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(decode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(decode));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(decoder)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(decoder));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(default)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(default));
@ -945,6 +946,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fix_imports)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fix_imports));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flags)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flags));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flush)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(flush));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(fold));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(follow_symlinks)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(follow_symlinks));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(format));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(from_param)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(from_param));
@ -975,6 +977,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(headers)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(headers));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hi)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hi));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hook)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hook));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hour));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(id)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(id));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ident)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ident));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(identity_hint)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(identity_hint));
@ -1059,11 +1062,14 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(metaclass)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(metaclass));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(metadata)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(metadata));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(method)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(method));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(microsecond));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(minute));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mod)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mod));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mode));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(module)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(module));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(module_globals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(module_globals));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(modules)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(modules));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(month));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mro)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mro));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(msg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(msg));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mycmp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mycmp));
@ -1168,6 +1174,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(salt)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(salt));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sched_priority)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sched_priority));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(scheduler)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(scheduler));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(second));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seek)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seek));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seekable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(seekable));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(selectors)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(selectors));
@ -1244,6 +1251,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type_params)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type_params));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tz)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tz));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tzinfo));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tzname)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tzname));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uid)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uid));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(unlink)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(unlink));

View file

@ -365,6 +365,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(d) STRUCT_FOR_ID(d)
STRUCT_FOR_ID(data) STRUCT_FOR_ID(data)
STRUCT_FOR_ID(database) STRUCT_FOR_ID(database)
STRUCT_FOR_ID(day)
STRUCT_FOR_ID(decode) STRUCT_FOR_ID(decode)
STRUCT_FOR_ID(decoder) STRUCT_FOR_ID(decoder)
STRUCT_FOR_ID(default) STRUCT_FOR_ID(default)
@ -434,6 +435,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(fix_imports) STRUCT_FOR_ID(fix_imports)
STRUCT_FOR_ID(flags) STRUCT_FOR_ID(flags)
STRUCT_FOR_ID(flush) STRUCT_FOR_ID(flush)
STRUCT_FOR_ID(fold)
STRUCT_FOR_ID(follow_symlinks) STRUCT_FOR_ID(follow_symlinks)
STRUCT_FOR_ID(format) STRUCT_FOR_ID(format)
STRUCT_FOR_ID(from_param) STRUCT_FOR_ID(from_param)
@ -464,6 +466,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(headers) STRUCT_FOR_ID(headers)
STRUCT_FOR_ID(hi) STRUCT_FOR_ID(hi)
STRUCT_FOR_ID(hook) STRUCT_FOR_ID(hook)
STRUCT_FOR_ID(hour)
STRUCT_FOR_ID(id) STRUCT_FOR_ID(id)
STRUCT_FOR_ID(ident) STRUCT_FOR_ID(ident)
STRUCT_FOR_ID(identity_hint) STRUCT_FOR_ID(identity_hint)
@ -548,11 +551,14 @@ struct _Py_global_strings {
STRUCT_FOR_ID(metaclass) STRUCT_FOR_ID(metaclass)
STRUCT_FOR_ID(metadata) STRUCT_FOR_ID(metadata)
STRUCT_FOR_ID(method) STRUCT_FOR_ID(method)
STRUCT_FOR_ID(microsecond)
STRUCT_FOR_ID(minute)
STRUCT_FOR_ID(mod) STRUCT_FOR_ID(mod)
STRUCT_FOR_ID(mode) STRUCT_FOR_ID(mode)
STRUCT_FOR_ID(module) STRUCT_FOR_ID(module)
STRUCT_FOR_ID(module_globals) STRUCT_FOR_ID(module_globals)
STRUCT_FOR_ID(modules) STRUCT_FOR_ID(modules)
STRUCT_FOR_ID(month)
STRUCT_FOR_ID(mro) STRUCT_FOR_ID(mro)
STRUCT_FOR_ID(msg) STRUCT_FOR_ID(msg)
STRUCT_FOR_ID(mycmp) STRUCT_FOR_ID(mycmp)
@ -657,6 +663,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(salt) STRUCT_FOR_ID(salt)
STRUCT_FOR_ID(sched_priority) STRUCT_FOR_ID(sched_priority)
STRUCT_FOR_ID(scheduler) STRUCT_FOR_ID(scheduler)
STRUCT_FOR_ID(second)
STRUCT_FOR_ID(seek) STRUCT_FOR_ID(seek)
STRUCT_FOR_ID(seekable) STRUCT_FOR_ID(seekable)
STRUCT_FOR_ID(selectors) STRUCT_FOR_ID(selectors)
@ -733,6 +740,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(type) STRUCT_FOR_ID(type)
STRUCT_FOR_ID(type_params) STRUCT_FOR_ID(type_params)
STRUCT_FOR_ID(tz) STRUCT_FOR_ID(tz)
STRUCT_FOR_ID(tzinfo)
STRUCT_FOR_ID(tzname) STRUCT_FOR_ID(tzname)
STRUCT_FOR_ID(uid) STRUCT_FOR_ID(uid)
STRUCT_FOR_ID(unlink) STRUCT_FOR_ID(unlink)

View file

@ -874,6 +874,7 @@ extern "C" {
INIT_ID(d), \ INIT_ID(d), \
INIT_ID(data), \ INIT_ID(data), \
INIT_ID(database), \ INIT_ID(database), \
INIT_ID(day), \
INIT_ID(decode), \ INIT_ID(decode), \
INIT_ID(decoder), \ INIT_ID(decoder), \
INIT_ID(default), \ INIT_ID(default), \
@ -943,6 +944,7 @@ extern "C" {
INIT_ID(fix_imports), \ INIT_ID(fix_imports), \
INIT_ID(flags), \ INIT_ID(flags), \
INIT_ID(flush), \ INIT_ID(flush), \
INIT_ID(fold), \
INIT_ID(follow_symlinks), \ INIT_ID(follow_symlinks), \
INIT_ID(format), \ INIT_ID(format), \
INIT_ID(from_param), \ INIT_ID(from_param), \
@ -973,6 +975,7 @@ extern "C" {
INIT_ID(headers), \ INIT_ID(headers), \
INIT_ID(hi), \ INIT_ID(hi), \
INIT_ID(hook), \ INIT_ID(hook), \
INIT_ID(hour), \
INIT_ID(id), \ INIT_ID(id), \
INIT_ID(ident), \ INIT_ID(ident), \
INIT_ID(identity_hint), \ INIT_ID(identity_hint), \
@ -1057,11 +1060,14 @@ extern "C" {
INIT_ID(metaclass), \ INIT_ID(metaclass), \
INIT_ID(metadata), \ INIT_ID(metadata), \
INIT_ID(method), \ INIT_ID(method), \
INIT_ID(microsecond), \
INIT_ID(minute), \
INIT_ID(mod), \ INIT_ID(mod), \
INIT_ID(mode), \ INIT_ID(mode), \
INIT_ID(module), \ INIT_ID(module), \
INIT_ID(module_globals), \ INIT_ID(module_globals), \
INIT_ID(modules), \ INIT_ID(modules), \
INIT_ID(month), \
INIT_ID(mro), \ INIT_ID(mro), \
INIT_ID(msg), \ INIT_ID(msg), \
INIT_ID(mycmp), \ INIT_ID(mycmp), \
@ -1166,6 +1172,7 @@ extern "C" {
INIT_ID(salt), \ INIT_ID(salt), \
INIT_ID(sched_priority), \ INIT_ID(sched_priority), \
INIT_ID(scheduler), \ INIT_ID(scheduler), \
INIT_ID(second), \
INIT_ID(seek), \ INIT_ID(seek), \
INIT_ID(seekable), \ INIT_ID(seekable), \
INIT_ID(selectors), \ INIT_ID(selectors), \
@ -1242,6 +1249,7 @@ extern "C" {
INIT_ID(type), \ INIT_ID(type), \
INIT_ID(type_params), \ INIT_ID(type_params), \
INIT_ID(tz), \ INIT_ID(tz), \
INIT_ID(tzinfo), \
INIT_ID(tzname), \ INIT_ID(tzname), \
INIT_ID(uid), \ INIT_ID(uid), \
INIT_ID(unlink), \ INIT_ID(unlink), \

View file

@ -936,6 +936,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(database); string = &_Py_ID(database);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(day);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(decode); string = &_Py_ID(decode);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
@ -1143,6 +1146,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(flush); string = &_Py_ID(flush);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(fold);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(follow_symlinks); string = &_Py_ID(follow_symlinks);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
@ -1233,6 +1239,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(hook); string = &_Py_ID(hook);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(hour);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(id); string = &_Py_ID(id);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
@ -1485,6 +1494,12 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(method); string = &_Py_ID(method);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(microsecond);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(minute);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(mod); string = &_Py_ID(mod);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
@ -1500,6 +1515,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(modules); string = &_Py_ID(modules);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(month);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(mro); string = &_Py_ID(mro);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
@ -1812,6 +1830,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(scheduler); string = &_Py_ID(scheduler);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(second);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(seek); string = &_Py_ID(seek);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
@ -2040,6 +2061,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
string = &_Py_ID(tz); string = &_Py_ID(tz);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(tzinfo);
assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string);
string = &_Py_ID(tzname); string = &_Py_ID(tzname);
assert(_PyUnicode_CheckConsistency(string, 1)); assert(_PyUnicode_CheckConsistency(string, 1));
_PyUnicode_InternInPlace(interp, &string); _PyUnicode_InternInPlace(interp, &string);

View file

@ -0,0 +1,2 @@
Speed-up :func:`datetime.datetime.replace`, :func:`datetime.date.replace` and
:func:`datetime.time.replace`.

View file

@ -61,16 +61,6 @@ static datetime_state _datetime_global_state;
#define STATIC_STATE() (&_datetime_global_state) #define STATIC_STATE() (&_datetime_global_state)
/*[clinic input]
module datetime
class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType"
class datetime.date "PyDateTime_Date *" "&PyDateTime_DateType"
class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCalendarDateType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81bec0fa19837f63]*/
#include "clinic/_datetimemodule.c.h"
/* We require that C int be at least 32 bits, and use int virtually /* We require that C int be at least 32 bits, and use int virtually
* everywhere. In just a few cases we use a temp long, where a Python * everywhere. In just a few cases we use a temp long, where a Python
* API returns a C long. In such cases, we have to ensure that the * API returns a C long. In such cases, we have to ensure that the
@ -161,6 +151,17 @@ static PyTypeObject PyDateTime_TimeZoneType;
static int check_tzinfo_subclass(PyObject *p); static int check_tzinfo_subclass(PyObject *p);
/*[clinic input]
module datetime
class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType"
class datetime.date "PyDateTime_Date *" "&PyDateTime_DateType"
class datetime.time "PyDateTime_Time *" "&PyDateTime_TimeType"
class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCalendarDateType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6f65a48dd22fa40f]*/
#include "clinic/_datetimemodule.c.h"
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Math utilities. * Math utilities.
@ -3466,24 +3467,22 @@ date_timetuple(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
0, 0, 0, -1); 0, 0, 0, -1);
} }
static PyObject * /*[clinic input]
date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw) datetime.date.replace
{
PyObject *clone;
PyObject *tuple;
int year = GET_YEAR(self);
int month = GET_MONTH(self);
int day = GET_DAY(self);
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws, year: int(c_default="GET_YEAR(self)") = unchanged
&year, &month, &day)) month: int(c_default="GET_MONTH(self)") = unchanged
return NULL; day: int(c_default="GET_DAY(self)") = unchanged
tuple = Py_BuildValue("iii", year, month, day);
if (tuple == NULL) Return date with new specified fields.
return NULL; [clinic start generated code]*/
clone = date_new(Py_TYPE(self), tuple, NULL);
Py_DECREF(tuple); static PyObject *
return clone; datetime_date_replace_impl(PyDateTime_Date *self, int year, int month,
int day)
/*[clinic end generated code: output=2a9430d1e6318aeb input=0d1f02685b3e90f6]*/
{
return new_date_ex(year, month, day, Py_TYPE(self));
} }
static Py_hash_t static Py_hash_t
@ -3596,10 +3595,9 @@ static PyMethodDef date_methods[] = {
PyDoc_STR("Return the day of the week represented by the date.\n" PyDoc_STR("Return the day of the week represented by the date.\n"
"Monday == 0 ... Sunday == 6")}, "Monday == 0 ... Sunday == 6")},
{"replace", _PyCFunction_CAST(date_replace), METH_VARARGS | METH_KEYWORDS, DATETIME_DATE_REPLACE_METHODDEF
PyDoc_STR("Return date with new specified fields.")},
{"__replace__", _PyCFunction_CAST(date_replace), METH_VARARGS | METH_KEYWORDS}, {"__replace__", _PyCFunction_CAST(datetime_date_replace), METH_FASTCALL | METH_KEYWORDS},
{"__reduce__", (PyCFunction)date_reduce, METH_NOARGS, {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS,
PyDoc_STR("__reduce__() -> (cls, state)")}, PyDoc_STR("__reduce__() -> (cls, state)")},
@ -4573,36 +4571,28 @@ time_hash(PyDateTime_Time *self)
return self->hashcode; return self->hashcode;
} }
static PyObject * /*[clinic input]
time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) datetime.time.replace
{
PyObject *clone;
PyObject *tuple;
int hh = TIME_GET_HOUR(self);
int mm = TIME_GET_MINUTE(self);
int ss = TIME_GET_SECOND(self);
int us = TIME_GET_MICROSECOND(self);
PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
int fold = TIME_GET_FOLD(self);
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i:replace", hour: int(c_default="TIME_GET_HOUR(self)") = unchanged
time_kws, minute: int(c_default="TIME_GET_MINUTE(self)") = unchanged
&hh, &mm, &ss, &us, &tzinfo, &fold)) second: int(c_default="TIME_GET_SECOND(self)") = unchanged
return NULL; microsecond: int(c_default="TIME_GET_MICROSECOND(self)") = unchanged
if (fold != 0 && fold != 1) { tzinfo: object(c_default="HASTZINFO(self) ? self->tzinfo : Py_None") = unchanged
PyErr_SetString(PyExc_ValueError, *
"fold must be either 0 or 1"); fold: int(c_default="TIME_GET_FOLD(self)") = unchanged
return NULL;
} Return time with new specified fields.
tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo); [clinic start generated code]*/
if (tuple == NULL)
return NULL; static PyObject *
clone = time_new(Py_TYPE(self), tuple, NULL); datetime_time_replace_impl(PyDateTime_Time *self, int hour, int minute,
if (clone != NULL) { int second, int microsecond, PyObject *tzinfo,
TIME_SET_FOLD(clone, fold); int fold)
} /*[clinic end generated code: output=0b89a44c299e4f80 input=9b6a35b1e704b0ca]*/
Py_DECREF(tuple); {
return clone; return new_time_ex2(hour, minute, second, microsecond, tzinfo, fold,
Py_TYPE(self));
} }
static PyObject * static PyObject *
@ -4732,10 +4722,9 @@ static PyMethodDef time_methods[] = {
{"dst", (PyCFunction)time_dst, METH_NOARGS, {"dst", (PyCFunction)time_dst, METH_NOARGS,
PyDoc_STR("Return self.tzinfo.dst(self).")}, PyDoc_STR("Return self.tzinfo.dst(self).")},
{"replace", _PyCFunction_CAST(time_replace), METH_VARARGS | METH_KEYWORDS, DATETIME_TIME_REPLACE_METHODDEF
PyDoc_STR("Return time with new specified fields.")},
{"__replace__", _PyCFunction_CAST(time_replace), METH_VARARGS | METH_KEYWORDS}, {"__replace__", _PyCFunction_CAST(datetime_time_replace), METH_FASTCALL | METH_KEYWORDS},
{"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS, {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS,
PyDoc_STR("string -> time from a string in ISO 8601 format")}, PyDoc_STR("string -> time from a string in ISO 8601 format")},
@ -6042,40 +6031,32 @@ datetime_hash(PyDateTime_DateTime *self)
return self->hashcode; return self->hashcode;
} }
static PyObject * /*[clinic input]
datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) datetime.datetime.replace
{
PyObject *clone;
PyObject *tuple;
int y = GET_YEAR(self);
int m = GET_MONTH(self);
int d = GET_DAY(self);
int hh = DATE_GET_HOUR(self);
int mm = DATE_GET_MINUTE(self);
int ss = DATE_GET_SECOND(self);
int us = DATE_GET_MICROSECOND(self);
PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
int fold = DATE_GET_FOLD(self);
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace", year: int(c_default="GET_YEAR(self)") = unchanged
datetime_kws, month: int(c_default="GET_MONTH(self)") = unchanged
&y, &m, &d, &hh, &mm, &ss, &us, day: int(c_default="GET_DAY(self)") = unchanged
&tzinfo, &fold)) hour: int(c_default="DATE_GET_HOUR(self)") = unchanged
return NULL; minute: int(c_default="DATE_GET_MINUTE(self)") = unchanged
if (fold != 0 && fold != 1) { second: int(c_default="DATE_GET_SECOND(self)") = unchanged
PyErr_SetString(PyExc_ValueError, microsecond: int(c_default="DATE_GET_MICROSECOND(self)") = unchanged
"fold must be either 0 or 1"); tzinfo: object(c_default="HASTZINFO(self) ? self->tzinfo : Py_None") = unchanged
return NULL; *
} fold: int(c_default="DATE_GET_FOLD(self)") = unchanged
tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
if (tuple == NULL) Return datetime with new specified fields.
return NULL; [clinic start generated code]*/
clone = datetime_new(Py_TYPE(self), tuple, NULL);
if (clone != NULL) { static PyObject *
DATE_SET_FOLD(clone, fold); datetime_datetime_replace_impl(PyDateTime_DateTime *self, int year,
} int month, int day, int hour, int minute,
Py_DECREF(tuple); int second, int microsecond, PyObject *tzinfo,
return clone; int fold)
/*[clinic end generated code: output=00bc96536833fddb input=9b38253d56d9bcad]*/
{
return new_datetime_ex2(year, month, day, hour, minute, second,
microsecond, tzinfo, fold, Py_TYPE(self));
} }
static PyObject * static PyObject *
@ -6597,10 +6578,9 @@ static PyMethodDef datetime_methods[] = {
{"dst", (PyCFunction)datetime_dst, METH_NOARGS, {"dst", (PyCFunction)datetime_dst, METH_NOARGS,
PyDoc_STR("Return self.tzinfo.dst(self).")}, PyDoc_STR("Return self.tzinfo.dst(self).")},
{"replace", _PyCFunction_CAST(datetime_replace), METH_VARARGS | METH_KEYWORDS, DATETIME_DATETIME_REPLACE_METHODDEF
PyDoc_STR("Return datetime with new specified fields.")},
{"__replace__", _PyCFunction_CAST(datetime_replace), METH_VARARGS | METH_KEYWORDS}, {"__replace__", _PyCFunction_CAST(datetime_datetime_replace), METH_FASTCALL | METH_KEYWORDS},
{"astimezone", _PyCFunction_CAST(datetime_astimezone), METH_VARARGS | METH_KEYWORDS, {"astimezone", _PyCFunction_CAST(datetime_astimezone), METH_VARARGS | METH_KEYWORDS,
PyDoc_STR("tz -> convert to local time in new timezone tz\n")}, PyDoc_STR("tz -> convert to local time in new timezone tz\n")},

View file

@ -82,6 +82,207 @@ exit:
return return_value; return return_value;
} }
PyDoc_STRVAR(datetime_date_replace__doc__,
"replace($self, /, year=unchanged, month=unchanged, day=unchanged)\n"
"--\n"
"\n"
"Return date with new specified fields.");
#define DATETIME_DATE_REPLACE_METHODDEF \
{"replace", _PyCFunction_CAST(datetime_date_replace), METH_FASTCALL|METH_KEYWORDS, datetime_date_replace__doc__},
static PyObject *
datetime_date_replace_impl(PyDateTime_Date *self, int year, int month,
int day);
static PyObject *
datetime_date_replace(PyDateTime_Date *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(year), &_Py_ID(month), &_Py_ID(day), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"year", "month", "day", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "replace",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int year = GET_YEAR(self);
int month = GET_MONTH(self);
int day = GET_DAY(self);
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 3, 0, argsbuf);
if (!args) {
goto exit;
}
if (!noptargs) {
goto skip_optional_pos;
}
if (args[0]) {
year = PyLong_AsInt(args[0]);
if (year == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[1]) {
month = PyLong_AsInt(args[1]);
if (month == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
day = PyLong_AsInt(args[2]);
if (day == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional_pos:
return_value = datetime_date_replace_impl(self, year, month, day);
exit:
return return_value;
}
PyDoc_STRVAR(datetime_time_replace__doc__,
"replace($self, /, hour=unchanged, minute=unchanged, second=unchanged,\n"
" microsecond=unchanged, tzinfo=unchanged, *, fold=unchanged)\n"
"--\n"
"\n"
"Return time with new specified fields.");
#define DATETIME_TIME_REPLACE_METHODDEF \
{"replace", _PyCFunction_CAST(datetime_time_replace), METH_FASTCALL|METH_KEYWORDS, datetime_time_replace__doc__},
static PyObject *
datetime_time_replace_impl(PyDateTime_Time *self, int hour, int minute,
int second, int microsecond, PyObject *tzinfo,
int fold);
static PyObject *
datetime_time_replace(PyDateTime_Time *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 6
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(hour), &_Py_ID(minute), &_Py_ID(second), &_Py_ID(microsecond), &_Py_ID(tzinfo), &_Py_ID(fold), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"hour", "minute", "second", "microsecond", "tzinfo", "fold", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "replace",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[6];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int hour = TIME_GET_HOUR(self);
int minute = TIME_GET_MINUTE(self);
int second = TIME_GET_SECOND(self);
int microsecond = TIME_GET_MICROSECOND(self);
PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
int fold = TIME_GET_FOLD(self);
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 5, 0, argsbuf);
if (!args) {
goto exit;
}
if (!noptargs) {
goto skip_optional_pos;
}
if (args[0]) {
hour = PyLong_AsInt(args[0]);
if (hour == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[1]) {
minute = PyLong_AsInt(args[1]);
if (minute == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[2]) {
second = PyLong_AsInt(args[2]);
if (second == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[3]) {
microsecond = PyLong_AsInt(args[3]);
if (microsecond == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[4]) {
tzinfo = args[4];
if (!--noptargs) {
goto skip_optional_pos;
}
}
skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
fold = PyLong_AsInt(args[5]);
if (fold == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional_kwonly:
return_value = datetime_time_replace_impl(self, hour, minute, second, microsecond, tzinfo, fold);
exit:
return return_value;
}
PyDoc_STRVAR(datetime_datetime_now__doc__, PyDoc_STRVAR(datetime_datetime_now__doc__,
"now($type, /, tz=None)\n" "now($type, /, tz=None)\n"
"--\n" "--\n"
@ -146,4 +347,153 @@ skip_optional_pos:
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=562813dd3e164794 input=a9049054013a1b77]*/
PyDoc_STRVAR(datetime_datetime_replace__doc__,
"replace($self, /, year=unchanged, month=unchanged, day=unchanged,\n"
" hour=unchanged, minute=unchanged, second=unchanged,\n"
" microsecond=unchanged, tzinfo=unchanged, *, fold=unchanged)\n"
"--\n"
"\n"
"Return datetime with new specified fields.");
#define DATETIME_DATETIME_REPLACE_METHODDEF \
{"replace", _PyCFunction_CAST(datetime_datetime_replace), METH_FASTCALL|METH_KEYWORDS, datetime_datetime_replace__doc__},
static PyObject *
datetime_datetime_replace_impl(PyDateTime_DateTime *self, int year,
int month, int day, int hour, int minute,
int second, int microsecond, PyObject *tzinfo,
int fold);
static PyObject *
datetime_datetime_replace(PyDateTime_DateTime *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 9
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
PyObject *ob_item[NUM_KEYWORDS];
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_item = { &_Py_ID(year), &_Py_ID(month), &_Py_ID(day), &_Py_ID(hour), &_Py_ID(minute), &_Py_ID(second), &_Py_ID(microsecond), &_Py_ID(tzinfo), &_Py_ID(fold), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
#else // !Py_BUILD_CORE
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"year", "month", "day", "hour", "minute", "second", "microsecond", "tzinfo", "fold", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "replace",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[9];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int year = GET_YEAR(self);
int month = GET_MONTH(self);
int day = GET_DAY(self);
int hour = DATE_GET_HOUR(self);
int minute = DATE_GET_MINUTE(self);
int second = DATE_GET_SECOND(self);
int microsecond = DATE_GET_MICROSECOND(self);
PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
int fold = DATE_GET_FOLD(self);
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 8, 0, argsbuf);
if (!args) {
goto exit;
}
if (!noptargs) {
goto skip_optional_pos;
}
if (args[0]) {
year = PyLong_AsInt(args[0]);
if (year == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[1]) {
month = PyLong_AsInt(args[1]);
if (month == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[2]) {
day = PyLong_AsInt(args[2]);
if (day == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[3]) {
hour = PyLong_AsInt(args[3]);
if (hour == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[4]) {
minute = PyLong_AsInt(args[4]);
if (minute == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[5]) {
second = PyLong_AsInt(args[5]);
if (second == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[6]) {
microsecond = PyLong_AsInt(args[6]);
if (microsecond == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[7]) {
tzinfo = args[7];
if (!--noptargs) {
goto skip_optional_pos;
}
}
skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
fold = PyLong_AsInt(args[8]);
if (fold == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional_kwonly:
return_value = datetime_datetime_replace_impl(self, year, month, day, hour, minute, second, microsecond, tzinfo, fold);
exit:
return return_value;
}
/*[clinic end generated code: output=c7a04b865b1e0890 input=a9049054013a1b77]*/