@@ -58,7 +58,6 @@ from pandas._libs.tslibs.dtypes cimport (
58
58
)
59
59
from pandas._libs.tslibs.nattype cimport (
60
60
NPY_NAT,
61
- c_NaT as NaT,
62
61
c_nat_strings as nat_strings,
63
62
)
64
63
from pandas._libs.tslibs.np_datetime cimport (
@@ -503,20 +502,18 @@ def array_strptime(
503
502
if seen_datetime_offset and not utc:
504
503
is_same_offsets = len (out_tzoffset_vals) == 1
505
504
if not is_same_offsets or (state.found_naive or state.found_other):
506
- result2 = _array_strptime_object_fallback (
507
- values, fmt = fmt, exact = exact, errors = errors, utc = utc
505
+ raise ValueError (
506
+ " cannot parse datetimes with mixed time zones unless ` utc=True` "
508
507
)
509
- return result2, None
510
508
elif tz_out is not None :
511
509
# GH#55693
512
510
tz_offset = out_tzoffset_vals.pop()
513
511
tz_out2 = timezone(timedelta(seconds = tz_offset))
514
512
if not tz_compare(tz_out, tz_out2):
515
- # e.g. test_to_datetime_mixed_offsets_with_utc_false_deprecated
516
- result2 = _array_strptime_object_fallback (
517
- values, fmt = fmt, exact = exact, errors = errors, utc = utc
513
+ # e.g. test_to_datetime_mixed_offsets_with_utc_false_removed
514
+ raise ValueError (
515
+ " cannot parse datetimes with mixed time zones unless ` utc=True` "
518
516
)
519
- return result2, None
520
517
# e.g. test_guess_datetime_format_with_parseable_formats
521
518
else :
522
519
# e.g. test_to_datetime_iso8601_with_timezone_valid
@@ -525,10 +522,9 @@ def array_strptime(
525
522
elif not utc:
526
523
if tz_out and (state.found_other or state.found_naive_str):
527
524
# found_other indicates a tz-naive int, float, dt64, or date
528
- result2 = _array_strptime_object_fallback (
529
- values, fmt = fmt, exact = exact, errors = errors, utc = utc
525
+ raise ValueError (
526
+ " cannot parse datetimes with mixed time zones unless ` utc=True` "
530
527
)
531
- return result2, None
532
528
533
529
if infer_reso:
534
530
if state.creso_ever_changed:
@@ -790,155 +786,6 @@ cdef tzinfo _parse_with_format(
790
786
return tz
791
787
792
788
793
- def _array_strptime_object_fallback (
794
- ndarray[object] values ,
795
- str fmt ,
796
- bint exact = True ,
797
- errors = " raise" ,
798
- bint utc = False ,
799
- ):
800
-
801
- cdef:
802
- Py_ssize_t i, n = len (values)
803
- npy_datetimestruct dts
804
- int64_t iresult
805
- object val
806
- tzinfo tz
807
- bint is_raise = errors== " raise"
808
- bint is_coerce = errors== " coerce"
809
- bint iso_format = format_is_iso(fmt)
810
- NPY_DATETIMEUNIT creso, out_bestunit, item_reso
811
- int out_local = 0 , out_tzoffset = 0
812
- bint string_to_dts_succeeded = 0
813
-
814
- assert is_raise or is_coerce
815
-
816
- item_reso = NPY_DATETIMEUNIT.NPY_FR_GENERIC
817
- format_regex, locale_time = _get_format_regex(fmt)
818
-
819
- result = np.empty(n, dtype = object )
820
-
821
- dts.us = dts.ps = dts.as = 0
822
-
823
- for i in range (n):
824
- val = values[i]
825
- try :
826
- if isinstance (val, str ):
827
- if len (val) == 0 or val in nat_strings:
828
- result[i] = NaT
829
- continue
830
- elif checknull_with_nat_and_na(val):
831
- result[i] = NaT
832
- continue
833
- elif PyDateTime_Check(val):
834
- result[i] = Timestamp(val)
835
- continue
836
- elif PyDate_Check(val):
837
- result[i] = Timestamp(val)
838
- continue
839
- elif cnp.is_datetime64_object(val):
840
- result[i] = Timestamp(val)
841
- continue
842
- elif (
843
- (is_integer_object(val) or is_float_object(val))
844
- and (val != val or val == NPY_NAT)
845
- ):
846
- result[i] = NaT
847
- continue
848
- else :
849
- val = str (val)
850
-
851
- if fmt == " ISO8601" :
852
- string_to_dts_succeeded = not string_to_dts(
853
- val, & dts, & out_bestunit, & out_local,
854
- & out_tzoffset, False , None , False
855
- )
856
- elif iso_format:
857
- string_to_dts_succeeded = not string_to_dts(
858
- val, & dts, & out_bestunit, & out_local,
859
- & out_tzoffset, False , fmt, exact
860
- )
861
- if string_to_dts_succeeded:
862
- # No error reported by string_to_dts, pick back up
863
- # where we left off
864
- creso = get_supported_reso(out_bestunit)
865
- try :
866
- value = npy_datetimestruct_to_datetime(creso, & dts)
867
- except OverflowError as err:
868
- raise OutOfBoundsDatetime(
869
- f" Out of bounds nanosecond timestamp: {val}"
870
- ) from err
871
- if out_local == 1 :
872
- tz = timezone(timedelta(minutes = out_tzoffset))
873
- value = tz_localize_to_utc_single(
874
- value, tz, ambiguous = " raise" , nonexistent = None , creso = creso
875
- )
876
- else :
877
- tz = None
878
- ts = Timestamp._from_value_and_reso(value, creso, tz)
879
- result[i] = ts
880
- continue
881
-
882
- if parse_today_now(val, & iresult, utc, NPY_FR_ns):
883
- result[i] = Timestamp(val)
884
- continue
885
-
886
- # Some ISO formats can't be parsed by string_to_dts
887
- # For example, 6-digit YYYYMD. So, if there's an error, and a format
888
- # was specified, then try the string-matching code below. If the format
889
- # specified was 'ISO8601', then we need to error, because
890
- # only string_to_dts handles mixed ISO8601 formats.
891
- if not string_to_dts_succeeded and fmt == " ISO8601" :
892
- raise ValueError (f" Time data {val} is not ISO8601 format" )
893
-
894
- tz = _parse_with_format(
895
- val, fmt, exact, format_regex, locale_time, & dts, & item_reso
896
- )
897
- try :
898
- iresult = npy_datetimestruct_to_datetime(item_reso, & dts)
899
- except OverflowError as err:
900
- raise OutOfBoundsDatetime(
901
- f" Out of bounds nanosecond timestamp: {val}"
902
- ) from err
903
- if tz is not None :
904
- iresult = tz_localize_to_utc_single(
905
- iresult, tz, ambiguous = " raise" , nonexistent = None , creso = item_reso
906
- )
907
- ts = Timestamp._from_value_and_reso(iresult, item_reso, tz)
908
- result[i] = ts
909
-
910
- except (ValueError , OutOfBoundsDatetime) as ex:
911
- ex.args = (
912
- f" {str(ex)}, at position {i}. You might want to try:\n "
913
- " - passing `format` if your strings have a consistent format;\n "
914
- " - passing `format='ISO8601'` if your strings are "
915
- " all ISO8601 but not necessarily in exactly the same format;\n "
916
- " - passing `format='mixed'`, and the format will be "
917
- " inferred for each element individually. "
918
- " You might want to use `dayfirst` alongside this." ,
919
- )
920
- if is_coerce:
921
- result[i] = NaT
922
- continue
923
- else :
924
- raise
925
-
926
- import warnings
927
-
928
- from pandas.util._exceptions import find_stack_level
929
- warnings.warn(
930
- " In a future version of pandas, parsing datetimes with mixed time "
931
- " zones will raise an error unless `utc=True`. Please specify `utc=True` "
932
- " to opt in to the new behaviour and silence this warning. "
933
- " To create a `Series` with mixed offsets and `object` dtype, "
934
- " please use `apply` and `datetime.datetime.strptime`" ,
935
- FutureWarning ,
936
- stacklevel = find_stack_level(),
937
- )
938
-
939
- return result
940
-
941
-
942
789
class TimeRE (_TimeRE ):
943
790
"""
944
791
Handle conversion from format directives to regexes.
0 commit comments