Skip to content

Commit 8425c97

Browse files
authored
PERF: Timestamp construction with tz and string offset (#55748)
1 parent 2641235 commit 8425c97

File tree

1 file changed

+30
-39
lines changed

1 file changed

+30
-39
lines changed

pandas/_libs/tslibs/conversion.pyx

+30-39
Original file line numberDiff line numberDiff line change
@@ -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

471454
cdef _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

Comments
 (0)