@@ -409,44 +409,22 @@ cdef _TSObject convert_datetime_to_tsobject(
409409 return obj
410410
411411
412- cdef _TSObject _create_tsobject_tz_using_offset(npy_datetimestruct dts,
413- int tzoffset, tzinfo tz = None ,
414- NPY_DATETIMEUNIT reso = NPY_FR_ns):
412+ cdef _adjust_tsobject_tz_using_offset(_TSObject obj, tzinfo tz):
415413 """
416- Convert a datetimestruct `dts`, along with initial timezone offset
417- `tzoffset` to a _TSObject (with timezone object `tz` - optional) .
414+ Convert a datetimestruct `obj. dts`, with an attached tzinfo to a new
415+ user-provided tz .
418416
419417 Parameters
420418 ----------
421- dts : npy_datetimestruct
422- tzoffset : int
423- tz : tzinfo or None
424- timezone for the timezone-aware output.
425- reso : NPY_DATETIMEUNIT, default NPY_FR_ns
426-
427- Returns
428- -------
429419 obj : _TSObject
420+ tz : tzinfo
421+ timezone for the timezone-aware output.
430422 """
431423 cdef:
432- _TSObject obj = _TSObject()
433- int64_t value # numpy dt64
434424 datetime dt
435425 Py_ssize_t pos
436-
437- value = npy_datetimestruct_to_datetime(reso, & dts)
438- obj.dts = dts
439- obj.tzinfo = timezone(timedelta(minutes = tzoffset))
440- obj.value = tz_localize_to_utc_single(
441- value, obj.tzinfo, ambiguous = None , nonexistent = None , creso = reso
442- )
443- obj.creso = reso
444- if tz is None :
445- check_overflows(obj, reso)
446- return obj
447-
448- cdef:
449- Localizer info = Localizer(tz, reso)
426+ int64_t ps = obj.dts.ps
427+ Localizer info = Localizer(tz, obj.creso)
450428
451429 # Infer fold from offset-adjusted obj.value
452430 # see PEP 495 https://www.python.org/dev/peps/pep-0495/#the-fold-attribute
@@ -462,10 +440,15 @@ cdef _TSObject _create_tsobject_tz_using_offset(npy_datetimestruct dts,
462440 dt = datetime(obj.dts.year, obj.dts.month, obj.dts.day,
463441 obj.dts.hour, obj.dts.min, obj.dts.sec,
464442 obj.dts.us, obj.tzinfo, fold = obj.fold)
465- obj = convert_datetime_to_tsobject(
466- dt, tz, nanos = obj.dts.ps // 1000 )
467- obj.ensure_reso(reso) # TODO: more performant to get reso right up front?
468- return obj
443+
444+ # The rest here is similar to the 2-tz path in convert_datetime_to_tsobject
445+ # but avoids re-calculating obj.value
446+ dt = dt.astimezone(tz)
447+ pydatetime_to_dtstruct(dt, & obj.dts)
448+ obj.tzinfo = dt.tzinfo
449+ obj.dts.ps = ps
450+ check_dts_bounds(& obj.dts, obj.creso)
451+ check_overflows(obj, obj.creso)
469452
470453
471454cdef _TSObject convert_str_to_tsobject(str ts, tzinfo tz, str unit,
@@ -502,6 +485,7 @@ cdef _TSObject convert_str_to_tsobject(str ts, tzinfo tz, str unit,
502485 datetime dt
503486 int64_t ival
504487 NPY_DATETIMEUNIT out_bestunit, reso
488+ _TSObject obj
505489
506490 if len (ts) == 0 or ts in nat_strings:
507491 obj = _TSObject()
@@ -525,21 +509,28 @@ cdef _TSObject convert_str_to_tsobject(str ts, tzinfo tz, str unit,
525509 if not string_to_dts_failed:
526510 reso = get_supported_reso(out_bestunit)
527511 check_dts_bounds(& dts, reso)
512+ obj = _TSObject()
513+ obj.dts = dts
514+ obj.creso = reso
515+ ival = npy_datetimestruct_to_datetime(reso, & dts)
516+
528517 if out_local == 1 :
529- return _create_tsobject_tz_using_offset(
530- dts, out_tzoffset, tz, reso
518+ obj.tzinfo = timezone(timedelta(minutes = out_tzoffset))
519+ obj.value = tz_localize_to_utc_single(
520+ ival, obj.tzinfo, ambiguous = " raise" , nonexistent = None , creso = reso
531521 )
522+ if tz is None :
523+ check_overflows(obj, reso)
524+ return obj
525+ _adjust_tsobject_tz_using_offset(obj, tz)
526+ return obj
532527 else :
533- ival = npy_datetimestruct_to_datetime(reso, & dts)
534528 if tz is not None :
535529 # shift for _localize_tso
536530 ival = tz_localize_to_utc_single(
537531 ival, tz, ambiguous = " raise" , nonexistent = None , creso = reso
538532 )
539- obj = _TSObject()
540- obj.dts = dts
541533 obj.value = ival
542- obj.creso = reso
543534 maybe_localize_tso(obj, tz, obj.creso)
544535 return obj
545536
0 commit comments