@@ -4685,18 +4685,88 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
46854685 return clone ;
46864686}
46874687
4688+ static PyObject *
4689+ local_timezone (PyObject * utc_time )
4690+ {
4691+ PyObject * result = NULL ;
4692+ struct tm * timep ;
4693+ time_t timestamp ;
4694+ long offset ;
4695+ PyObject * delta ;
4696+ PyObject * one_second ;
4697+ PyObject * seconds ;
4698+ PyObject * nameo = NULL ;
4699+ const char * zone = NULL ;
4700+
4701+ delta = datetime_subtract ((PyObject * )utc_time , PyDateTime_Epoch );
4702+ if (delta == NULL )
4703+ return NULL ;
4704+ one_second = new_delta (0 , 1 , 0 , 0 );
4705+ if (one_second == NULL )
4706+ goto error ;
4707+ seconds = divide_timedelta_timedelta ((PyDateTime_Delta * )delta ,
4708+ (PyDateTime_Delta * )one_second );
4709+ Py_DECREF (one_second );
4710+ if (seconds == NULL )
4711+ goto error ;
4712+ Py_DECREF (delta );
4713+ timestamp = PyLong_AsLong (seconds );
4714+ Py_DECREF (seconds );
4715+ if (timestamp == -1 && PyErr_Occurred ())
4716+ return NULL ;
4717+ timep = localtime (& timestamp );
4718+ #ifdef HAVE_STRUCT_TM_TM_ZONE
4719+ offset = timep -> tm_gmtoff ;
4720+ zone = timep -> tm_zone ;
4721+ delta = new_delta (0 , - offset , 0 , 0 );
4722+ #else /* HAVE_STRUCT_TM_TM_ZONE */
4723+ {
4724+ PyObject * local_time ;
4725+ Py_INCREF (utc_time -> tzinfo );
4726+ local_time = new_datetime (timep -> tm_year + 1900 , timep -> tm_mon + 1 ,
4727+ timep -> tm_mday , timep -> tm_hour , timep -> tm_min ,
4728+ timep -> tm_sec , utc_time -> tzinfo );
4729+ if (local_time == NULL ) {
4730+ Py_DECREF (utc_time -> tzinfo );
4731+ goto error ;
4732+ }
4733+ delta = datetime_subtract (local_time , utc_time );
4734+ /* XXX: before relying on tzname, we should compare delta
4735+ to the offset implied by timezone/altzone */
4736+ if (daylight && timep -> tm_isdst >= 0 )
4737+ zone = tzname [timep -> tm_isdst % 2 ];
4738+ else
4739+ zone = tzname [0 ];
4740+ Py_DECREF (local_time );
4741+ }
4742+ #endif /* HAVE_STRUCT_TM_TM_ZONE */
4743+ if (zone != NULL ) {
4744+ nameo = PyUnicode_DecodeLocale (zone , "surrogateescape" );
4745+ if (nameo == NULL )
4746+ goto error ;
4747+ }
4748+ result = new_timezone (delta , nameo );
4749+ Py_DECREF (nameo );
4750+ error :
4751+ Py_DECREF (delta );
4752+ return result ;
4753+ }
4754+
46884755static PyObject *
46894756datetime_astimezone (PyDateTime_DateTime * self , PyObject * args , PyObject * kw )
46904757{
46914758 PyObject * result ;
46924759 PyObject * offset ;
46934760 PyObject * temp ;
4694- PyObject * tzinfo ;
4761+ PyObject * tzinfo = Py_None ;
46954762 _Py_IDENTIFIER (fromutc );
46964763 static char * keywords [] = {"tz" , NULL };
46974764
4698- if (! PyArg_ParseTupleAndKeywords (args , kw , "O!:astimezone" , keywords ,
4699- & PyDateTime_TZInfoType , & tzinfo ))
4765+ if (! PyArg_ParseTupleAndKeywords (args , kw , "|O:astimezone" , keywords ,
4766+ & tzinfo ))
4767+ return NULL ;
4768+
4769+ if (check_tzinfo_subclass (tzinfo ) == -1 )
47004770 return NULL ;
47014771
47024772 if (!HASTZINFO (self ) || self -> tzinfo == Py_None )
@@ -4729,8 +4799,16 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
47294799
47304800 /* Attach new tzinfo and let fromutc() do the rest. */
47314801 temp = ((PyDateTime_DateTime * )result )-> tzinfo ;
4802+ if (tzinfo == Py_None ) {
4803+ tzinfo = local_timezone (result );
4804+ if (tzinfo == NULL ) {
4805+ Py_DECREF (result );
4806+ return NULL ;
4807+ }
4808+ }
4809+ else
4810+ Py_INCREF (tzinfo );
47324811 ((PyDateTime_DateTime * )result )-> tzinfo = tzinfo ;
4733- Py_INCREF (tzinfo );
47344812 Py_DECREF (temp );
47354813
47364814 temp = result ;
0 commit comments