@@ -382,7 +382,10 @@ cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz):
382
382
converted: int64
383
383
"""
384
384
cdef:
385
- int64_t arr[1 ]
385
+ int64_t delta
386
+ int64_t[:] deltas
387
+ ndarray[int64_t, ndim= 1 ] trans
388
+ intp_t pos
386
389
387
390
if val == NPY_NAT:
388
391
return val
@@ -391,9 +394,14 @@ cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz):
391
394
return val
392
395
elif is_tzlocal(tz):
393
396
return _tz_convert_tzlocal_utc(val, tz, to_utc = False )
397
+ elif is_fixed_offset(tz):
398
+ _, deltas, _ = get_dst_info(tz)
399
+ delta = deltas[0 ]
400
+ return val + delta
394
401
else :
395
- arr[0 ] = val
396
- return _tz_convert_dst(arr, tz)[0 ]
402
+ trans, deltas, _ = get_dst_info(tz)
403
+ pos = trans.searchsorted(val, side = " right" ) - 1
404
+ return val + deltas[pos]
397
405
398
406
399
407
def tz_convert_from_utc (int64_t[:] vals , tzinfo tz ):
@@ -435,9 +443,12 @@ cdef int64_t[:] _tz_convert_from_utc(int64_t[:] vals, tzinfo tz):
435
443
converted : ndarray[int64_t]
436
444
"""
437
445
cdef:
438
- int64_t[:] converted
446
+ int64_t[:] converted, deltas
439
447
Py_ssize_t i, n = len (vals)
440
- int64_t val
448
+ int64_t val, delta
449
+ intp_t[:] pos
450
+ ndarray[int64_t] trans
451
+ str typ
441
452
442
453
if is_utc(tz):
443
454
converted = vals
@@ -450,7 +461,35 @@ cdef int64_t[:] _tz_convert_from_utc(int64_t[:] vals, tzinfo tz):
450
461
else :
451
462
converted[i] = _tz_convert_tzlocal_utc(val, tz, to_utc = False )
452
463
else :
453
- converted = _tz_convert_dst(vals, tz)
464
+ converted = np.empty(n, dtype = np.int64)
465
+
466
+ trans, deltas, typ = get_dst_info(tz)
467
+
468
+ if typ not in [" pytz" , " dateutil" ]:
469
+ # FixedOffset, we know len(deltas) == 1
470
+ delta = deltas[0 ]
471
+
472
+ for i in range (n):
473
+ val = vals[i]
474
+ if val == NPY_NAT:
475
+ converted[i] = val
476
+ else :
477
+ converted[i] = val + delta
478
+
479
+ else :
480
+ pos = trans.searchsorted(vals, side = " right" ) - 1
481
+
482
+ for i in range (n):
483
+ val = vals[i]
484
+ if val == NPY_NAT:
485
+ converted[i] = val
486
+ else :
487
+ if pos[i] < 0 :
488
+ # TODO: How is this reached? Should we be checking for
489
+ # it elsewhere?
490
+ raise ValueError (" First time before start of DST info" )
491
+
492
+ converted[i] = val + deltas[pos[i]]
454
493
455
494
return converted
456
495
@@ -537,67 +576,3 @@ cdef int64_t _tz_convert_tzlocal_utc(int64_t val, tzinfo tz, bint to_utc=True,
537
576
return val - delta
538
577
else :
539
578
return val + delta
540
-
541
-
542
- @ cython.boundscheck (False )
543
- @ cython.wraparound (False )
544
- cdef int64_t[:] _tz_convert_dst(const int64_t[:] values, tzinfo tz):
545
- """
546
- tz_convert for non-UTC non-tzlocal cases where we have to check
547
- DST transitions pointwise.
548
-
549
- Parameters
550
- ----------
551
- values : ndarray[int64_t]
552
- tz : tzinfo
553
-
554
- Returns
555
- -------
556
- result : ndarray[int64_t]
557
- """
558
- cdef:
559
- Py_ssize_t n = len (values)
560
- Py_ssize_t i
561
- intp_t[:] pos
562
- int64_t[:] result = np.empty(n, dtype = np.int64)
563
- ndarray[int64_t] trans
564
- int64_t[:] deltas
565
- int64_t v, delta
566
- str typ
567
-
568
- # tz is assumed _not_ to be tzlocal; that should go
569
- # through _tz_convert_tzlocal_utc
570
-
571
- trans, deltas, typ = get_dst_info(tz)
572
-
573
- if typ not in [" pytz" , " dateutil" ]:
574
- # FixedOffset, we know len(deltas) == 1
575
- delta = deltas[0 ]
576
-
577
- for i in range (n):
578
- v = values[i]
579
- if v == NPY_NAT:
580
- result[i] = v
581
- else :
582
- result[i] = v + delta
583
-
584
- else :
585
- # Previously, this search was done pointwise to try and benefit
586
- # from getting to skip searches for iNaTs. However, it seems call
587
- # overhead dominates the search time so doing it once in bulk
588
- # is substantially faster (GH#24603)
589
- pos = trans.searchsorted(values, side = " right" ) - 1
590
-
591
- for i in range (n):
592
- v = values[i]
593
- if v == NPY_NAT:
594
- result[i] = v
595
- else :
596
- if pos[i] < 0 :
597
- # TODO: How is this reached? Should we be checking for
598
- # it elsewhere?
599
- raise ValueError (" First time before start of DST info" )
600
-
601
- result[i] = v + deltas[pos[i]]
602
-
603
- return result
0 commit comments