@@ -600,6 +600,18 @@ get_tzinfo_member(PyObject *self)
600600 return tzinfo ;
601601}
602602
603+ /* self is a datetimetz. Replace its tzinfo member. */
604+ void
605+ replace_tzinfo (PyObject * self , PyObject * newtzinfo )
606+ {
607+ assert (self != NULL );
608+ assert (PyDateTimeTZ_Check (self ));
609+ assert (check_tzinfo_subclass (newtzinfo ) >= 0 );
610+ Py_INCREF (newtzinfo );
611+ Py_DECREF (((PyDateTime_DateTimeTZ * )self )-> tzinfo );
612+ ((PyDateTime_DateTimeTZ * )self )-> tzinfo = newtzinfo ;
613+ }
614+
603615/* Internal helper.
604616 * Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
605617 * result. tzinfo must be an instance of the tzinfo class. If the method
@@ -2915,10 +2927,7 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
29152927 TIME_GET_MICROSECOND (time ));
29162928 if (result && PyTimeTZ_Check (time ) && PyDateTimeTZ_Check (result )) {
29172929 /* Copy the tzinfo field. */
2918- PyObject * tzinfo = ((PyDateTime_TimeTZ * )time )-> tzinfo ;
2919- Py_INCREF (tzinfo );
2920- Py_DECREF (((PyDateTime_DateTimeTZ * )result )-> tzinfo );
2921- ((PyDateTime_DateTimeTZ * )result )-> tzinfo = tzinfo ;
2930+ replace_tzinfo (result , ((PyDateTime_TimeTZ * )time )-> tzinfo );
29222931 }
29232932 return result ;
29242933}
@@ -3246,6 +3255,24 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
32463255 return clone ;
32473256}
32483257
3258+ static PyObject *
3259+ datetime_astimezone (PyDateTime_DateTime * self , PyObject * args , PyObject * kw )
3260+ {
3261+ PyObject * tzinfo ;
3262+ static char * keywords [] = {"tz" , NULL };
3263+
3264+ if (! PyArg_ParseTupleAndKeywords (args , kw , "O:astimezone" , keywords ,
3265+ & tzinfo ))
3266+ return NULL ;
3267+ if (check_tzinfo_subclass (tzinfo ) < 0 )
3268+ return NULL ;
3269+ return new_datetimetz (GET_YEAR (self ), GET_MONTH (self ), GET_DAY (self ),
3270+ DATE_GET_HOUR (self ), DATE_GET_MINUTE (self ),
3271+ DATE_GET_SECOND (self ),
3272+ DATE_GET_MICROSECOND (self ),
3273+ tzinfo );
3274+ }
3275+
32493276static PyObject *
32503277datetime_timetuple (PyDateTime_DateTime * self )
32513278{
@@ -3397,6 +3424,9 @@ static PyMethodDef datetime_methods[] = {
33973424 {"replace" , (PyCFunction )datetime_replace , METH_KEYWORDS ,
33983425 PyDoc_STR ("Return datetime with new specified fields." )},
33993426
3427+ {"astimezone" , (PyCFunction )datetime_astimezone , METH_KEYWORDS ,
3428+ PyDoc_STR ("tz -> datetimetz with same date & time, and tzinfo=tz\n" )},
3429+
34003430 {"__setstate__" , (PyCFunction )datetime_setstate , METH_O ,
34013431 PyDoc_STR ("__setstate__(state)" )},
34023432
@@ -4398,20 +4428,6 @@ static PyGetSetDef datetimetz_getset[] = {
43984428 * optional tzinfo argument.
43994429 */
44004430
4401- /* Internal helper.
4402- * self is a datetimetz. Replace its tzinfo member.
4403- */
4404- void
4405- replace_tzinfo (PyObject * self , PyObject * newtzinfo )
4406- {
4407- assert (self != NULL );
4408- assert (newtzinfo != NULL );
4409- assert (PyDateTimeTZ_Check (self ));
4410- Py_INCREF (newtzinfo );
4411- Py_DECREF (((PyDateTime_DateTimeTZ * )self )-> tzinfo );
4412- ((PyDateTime_DateTimeTZ * )self )-> tzinfo = newtzinfo ;
4413- }
4414-
44154431static char * datetimetz_kws [] = {
44164432 "year" , "month" , "day" , "hour" , "minute" , "second" ,
44174433 "microsecond" , "tzinfo" , NULL
@@ -4696,6 +4712,53 @@ datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
46964712 return clone ;
46974713}
46984714
4715+ static PyObject *
4716+ datetimetz_astimezone (PyDateTime_DateTimeTZ * self , PyObject * args ,
4717+ PyObject * kw )
4718+ {
4719+ int y = GET_YEAR (self );
4720+ int m = GET_MONTH (self );
4721+ int d = GET_DAY (self );
4722+ int hh = DATE_GET_HOUR (self );
4723+ int mm = DATE_GET_MINUTE (self );
4724+ int ss = DATE_GET_SECOND (self );
4725+ int us = DATE_GET_MICROSECOND (self );
4726+
4727+ PyObject * tzinfo ;
4728+ static char * keywords [] = {"tz" , NULL };
4729+
4730+ if (! PyArg_ParseTupleAndKeywords (args , kw , "O:astimezone" , keywords ,
4731+ & tzinfo ))
4732+ return NULL ;
4733+ if (check_tzinfo_subclass (tzinfo ) < 0 )
4734+ return NULL ;
4735+
4736+ if (tzinfo != Py_None && self -> tzinfo != Py_None ) {
4737+ int none ;
4738+ int selfoffset ;
4739+ selfoffset = call_utcoffset (self -> tzinfo ,
4740+ (PyObject * )self ,
4741+ & none );
4742+ if (selfoffset == -1 && PyErr_Occurred ())
4743+ return NULL ;
4744+ if (! none ) {
4745+ int tzoffset ;
4746+ tzoffset = call_utcoffset (tzinfo ,
4747+ (PyObject * )self ,
4748+ & none );
4749+ if (tzoffset == -1 && PyErr_Occurred ())
4750+ return NULL ;
4751+ if (! none ) {
4752+ mm -= selfoffset - tzoffset ;
4753+ if (normalize_datetime (& y , & m , & d ,
4754+ & hh , & mm , & ss , & us ) < 0 )
4755+ return NULL ;
4756+ }
4757+ }
4758+ }
4759+ return new_datetimetz (y , m , d , hh , mm , ss , us , tzinfo );
4760+ }
4761+
46994762static PyObject *
47004763datetimetz_timetuple (PyDateTime_DateTimeTZ * self )
47014764{
@@ -4908,6 +4971,9 @@ static PyMethodDef datetimetz_methods[] = {
49084971 {"replace" , (PyCFunction )datetimetz_replace , METH_KEYWORDS ,
49094972 PyDoc_STR ("Return datetimetz with new specified fields." )},
49104973
4974+ {"astimezone" , (PyCFunction )datetimetz_astimezone , METH_KEYWORDS ,
4975+ PyDoc_STR ("tz -> convert to local time in new timezone tz\n" )},
4976+
49114977 {"__setstate__" , (PyCFunction )datetimetz_setstate , METH_O ,
49124978 PyDoc_STR ("__setstate__(state)" )},
49134979
0 commit comments