@@ -847,6 +847,27 @@ new_date_ex(int year, int month, int day, PyTypeObject *type)
847847#define new_date (year , month , day ) \
848848 new_date_ex(year, month, day, &PyDateTime_DateType)
849849
850+ // Forward declaration
851+ static PyObject * new_datetime_ex (int , int , int , int , int , int , int ,
852+ PyObject * , PyTypeObject * );
853+
854+ /* Create date instance with no range checking, or call subclass constructor */
855+ static PyObject *
856+ new_date_subclass_ex (int year , int month , int day , PyObject * cls ) {
857+ PyObject * result ;
858+ // We have "fast path" constructors for two subclasses: date and datetime
859+ if ((PyTypeObject * )cls == & PyDateTime_DateType ) {
860+ result = new_date_ex (year , month , day , (PyTypeObject * )cls );
861+ } else if ((PyTypeObject * )cls == & PyDateTime_DateTimeType ) {
862+ result = new_datetime_ex (year , month , day , 0 , 0 , 0 , 0 , Py_None ,
863+ (PyTypeObject * )cls );
864+ } else {
865+ result = PyObject_CallFunction (cls , "iii" , year , month , day );
866+ }
867+
868+ return result ;
869+ }
870+
850871/* Create a datetime instance with no range checking. */
851872static PyObject *
852873new_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,
894915 new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \
895916 &PyDateTime_DateTimeType)
896917
918+ static PyObject *
919+ new_datetime_subclass_fold_ex (int year , int month , int day , int hour , int minute ,
920+ int second , int usecond , PyObject * tzinfo ,
921+ int fold , PyObject * cls ) {
922+ PyObject * dt ;
923+ if ((PyTypeObject * )cls == & PyDateTime_DateTimeType ) {
924+ // Use the fast path constructor
925+ dt = new_datetime (year , month , day , hour , minute , second , usecond ,
926+ tzinfo , fold );
927+ } else {
928+ // Subclass
929+ dt = PyObject_CallFunction (cls , "iiiiiiiO" ,
930+ year ,
931+ month ,
932+ day ,
933+ hour ,
934+ minute ,
935+ second ,
936+ usecond ,
937+ tzinfo );
938+ }
939+
940+ return dt ;
941+ }
942+
943+ static PyObject *
944+ new_datetime_subclass_ex (int year , int month , int day , int hour , int minute ,
945+ int second , int usecond , PyObject * tzinfo ,
946+ PyObject * cls ) {
947+ return new_datetime_subclass_fold_ex (year , month , day , hour , minute ,
948+ second , usecond , tzinfo , 0 ,
949+ cls );
950+ }
951+
897952/* Create a time instance with no range checking. */
898953static PyObject *
899954new_time_ex2 (int hour , int minute , int second , int usecond ,
@@ -2743,10 +2798,10 @@ date_local_from_object(PyObject *cls, PyObject *obj)
27432798 if (_PyTime_localtime (t , & tm ) != 0 )
27442799 return NULL ;
27452800
2746- return PyObject_CallFunction ( cls , "iii" ,
2747- tm .tm_year + 1900 ,
2748- tm .tm_mon + 1 ,
2749- tm . tm_mday );
2801+ return new_date_subclass_ex ( tm . tm_year + 1900 ,
2802+ tm .tm_mon + 1 ,
2803+ tm .tm_mday ,
2804+ cls );
27502805}
27512806
27522807/* Return new date from current time.
@@ -2809,8 +2864,7 @@ date_fromordinal(PyObject *cls, PyObject *args)
28092864 ">= 1" );
28102865 else {
28112866 ord_to_ymd (ordinal , & year , & month , & day );
2812- result = PyObject_CallFunction (cls , "iii" ,
2813- year , month , day );
2867+ result = new_date_subclass_ex (year , month , day , cls );
28142868 }
28152869 }
28162870 return result ;
@@ -2845,14 +2899,7 @@ date_fromisoformat(PyObject *cls, PyObject *dtstr) {
28452899 return NULL ;
28462900 }
28472901
2848- PyObject * result ;
2849- if ( (PyTypeObject * )cls == & PyDateTime_DateType ) {
2850- result = new_date_ex (year , month , day , (PyTypeObject * )cls );
2851- } else {
2852- result = PyObject_CallFunction (cls , "iii" , year , month , day );
2853- }
2854-
2855- return result ;
2902+ return new_date_subclass_ex (year , month , day , cls );
28562903}
28572904
28582905
@@ -4596,9 +4643,8 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
45964643 fold = 1 ;
45974644 }
45984645 }
4599- return new_datetime_ex2 (year , month , day , hour ,
4600- minute , second , us , tzinfo , fold ,
4601- (PyTypeObject * )cls );
4646+ return new_datetime_subclass_fold_ex (year , month , day , hour , minute ,
4647+ second , us , tzinfo , fold , cls );
46024648}
46034649
46044650/* Internal helper.
@@ -4764,17 +4810,16 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
47644810 else
47654811 tzinfo = Py_None ;
47664812 }
4767- result = PyObject_CallFunction (cls , "iiiiiiiO" ,
4768- GET_YEAR (date ),
4769- GET_MONTH (date ),
4770- GET_DAY (date ),
4771- TIME_GET_HOUR (time ),
4772- TIME_GET_MINUTE (time ),
4773- TIME_GET_SECOND (time ),
4774- TIME_GET_MICROSECOND (time ),
4775- tzinfo );
4776- if (result )
4777- DATE_SET_FOLD (result , TIME_GET_FOLD (time ));
4813+ result = new_datetime_subclass_fold_ex (GET_YEAR (date ),
4814+ GET_MONTH (date ),
4815+ GET_DAY (date ),
4816+ TIME_GET_HOUR (time ),
4817+ TIME_GET_MINUTE (time ),
4818+ TIME_GET_SECOND (time ),
4819+ TIME_GET_MICROSECOND (time ),
4820+ tzinfo ,
4821+ TIME_GET_FOLD (time ),
4822+ cls );
47784823 }
47794824 return result ;
47804825}
@@ -4832,23 +4877,8 @@ datetime_fromisoformat(PyObject* cls, PyObject *dtstr) {
48324877 return NULL ;
48334878 }
48344879
4835- PyObject * dt ;
4836- if ( (PyTypeObject * )cls == & PyDateTime_DateTimeType ) {
4837- // Use the fast path constructor
4838- dt = new_datetime (year , month , day , hour , minute , second , microsecond ,
4839- tzinfo , 0 );
4840- } else {
4841- // Subclass
4842- dt = PyObject_CallFunction (cls , "iiiiiiiO" ,
4843- year ,
4844- month ,
4845- day ,
4846- hour ,
4847- minute ,
4848- second ,
4849- microsecond ,
4850- tzinfo );
4851- }
4880+ PyObject * dt = new_datetime_subclass_ex (year , month , day , hour , minute ,
4881+ second , microsecond , tzinfo , cls );
48524882
48534883 Py_DECREF (tzinfo );
48544884 return dt ;
0 commit comments