Skip to content

Commit 499802c

Browse files
mroeschkejreback
authored andcommitted
BUG: Correctly localize naive datetime strings with Series and datetimetztype (pandas-dev#17415) (pandas-dev#17603)
1 parent ae4fe98 commit 499802c

File tree

3 files changed

+24
-8
lines changed

3 files changed

+24
-8
lines changed

doc/source/whatsnew/v0.23.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ Conversion
381381
- Fixed bug where comparing :class:`DatetimeIndex` failed to raise ``TypeError`` when attempting to compare timezone-aware and timezone-naive datetimelike objects (:issue:`18162`)
382382
- Bug in :class:`DatetimeIndex` where the repr was not showing high-precision time values at the end of a day (e.g., 23:59:59.999999999) (:issue:`19030`)
383383
- Bug where dividing a scalar timedelta-like object with :class:`TimedeltaIndex` performed the reciprocal operation (:issue:`19125`)
384-
-
384+
- Bug in localization of a naive, datetime string in a ``Series`` constructor with a ``datetime64[ns, tz]`` dtype (:issue:`174151`)
385385

386386
Indexing
387387
^^^^^^^^

pandas/core/dtypes/cast.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
is_integer_dtype,
2121
is_datetime_or_timedelta_dtype,
2222
is_bool_dtype, is_scalar,
23-
_string_dtypes,
23+
is_string_dtype, _string_dtypes,
2424
pandas_dtype,
2525
_ensure_int8, _ensure_int16,
2626
_ensure_int32, _ensure_int64,
@@ -1016,12 +1016,20 @@ def maybe_cast_to_datetime(value, dtype, errors='raise'):
10161016
if is_datetime64:
10171017
value = to_datetime(value, errors=errors)._values
10181018
elif is_datetime64tz:
1019-
# input has to be UTC at this point, so just
1020-
# localize
1021-
value = (to_datetime(value, errors=errors)
1022-
.tz_localize('UTC')
1023-
.tz_convert(dtype.tz)
1024-
)
1019+
# The string check can be removed once issue #13712
1020+
# is solved. String data that is passed with a
1021+
# datetime64tz is assumed to be naive which should
1022+
# be localized to the timezone.
1023+
is_dt_string = is_string_dtype(value)
1024+
value = to_datetime(value, errors=errors)
1025+
if is_dt_string:
1026+
# Strings here are naive, so directly localize
1027+
value = value.tz_localize(dtype.tz)
1028+
else:
1029+
# Numeric values are UTC at this point,
1030+
# so localize and convert
1031+
value = (value.tz_localize('UTC')
1032+
.tz_convert(dtype.tz))
10251033
elif is_timedelta64:
10261034
value = to_timedelta(value, errors=errors)._values
10271035
except (AttributeError, ValueError, TypeError):

pandas/tests/series/test_constructors.py

+8
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,14 @@ def test_constructor_with_datetime_tz(self):
707707
expected = Series(pd.DatetimeIndex(['NaT', 'NaT'], tz='US/Eastern'))
708708
assert_series_equal(s, expected)
709709

710+
@pytest.mark.parametrize('arg',
711+
['2013-01-01 00:00:00', pd.NaT, np.nan, None])
712+
def test_constructor_with_naive_string_and_datetimetz_dtype(self, arg):
713+
# GH 17415: With naive string
714+
result = Series([arg], dtype='datetime64[ns, CET]')
715+
expected = Series(pd.Timestamp(arg)).dt.tz_localize('CET')
716+
assert_series_equal(result, expected)
717+
710718
def test_construction_interval(self):
711719
# construction from interval & array of intervals
712720
index = IntervalIndex.from_breaks(np.arange(3), closed='right')

0 commit comments

Comments
 (0)