Skip to content

Commit a40e185

Browse files
committed
BUG: Bug in localizing an ambiguous timezone when a boolean is passed
closes pandas-dev#14402 closes pandas-dev#14405
1 parent 4d7c6e7 commit a40e185

File tree

3 files changed

+58
-11
lines changed

3 files changed

+58
-11
lines changed

doc/source/whatsnew/v0.19.1.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Bug Fixes
3434

3535

3636

37-
37+
- Bug in localizing an ambiguous timezone when a boolean is passed (:issue:`14402`)
3838

3939

4040

pandas/tseries/tests/test_timezones.py

+48-9
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
from pytz import NonExistentTimeError
1818

1919
import pandas.util.testing as tm
20-
from pandas.util.testing import assert_frame_equal, set_timezone
20+
from pandas.util.testing import (assert_frame_equal, assert_series_equal,
21+
set_timezone)
2122
from pandas.compat import lrange, zip
2223

2324
try:
@@ -535,6 +536,44 @@ def test_ambiguous_nat(self):
535536
# right is datetime64[ns, tzfile('/usr/share/zoneinfo/US/Eastern')]
536537
self.assert_numpy_array_equal(di_test.values, localized.values)
537538

539+
def test_ambiguous_bool(self):
540+
# make sure that we are correctly accepting bool values as ambiguous
541+
542+
# gh-14402
543+
t = Timestamp('2015-11-01 01:00:03')
544+
expected0 = Timestamp('2015-11-01 01:00:03-0500', tz='US/Central')
545+
expected1 = Timestamp('2015-11-01 01:00:03-0600', tz='US/Central')
546+
547+
def f():
548+
t.tz_localize('US/Central')
549+
self.assertRaises(pytz.AmbiguousTimeError, f)
550+
551+
result = t.tz_localize('US/Central', ambiguous=True)
552+
self.assertEqual(result, expected0)
553+
554+
result = t.tz_localize('US/Central', ambiguous=False)
555+
self.assertEqual(result, expected1)
556+
557+
s = Series([t])
558+
expected0 = Series([expected0])
559+
expected1 = Series([expected1])
560+
561+
def f():
562+
s.dt.tz_localize('US/Central')
563+
self.assertRaises(pytz.AmbiguousTimeError, f)
564+
565+
result = s.dt.tz_localize('US/Central', ambiguous=True)
566+
assert_series_equal(result, expected0)
567+
568+
result = s.dt.tz_localize('US/Central', ambiguous=[True])
569+
assert_series_equal(result, expected0)
570+
571+
result = s.dt.tz_localize('US/Central', ambiguous=False)
572+
assert_series_equal(result, expected1)
573+
574+
result = s.dt.tz_localize('US/Central', ambiguous=[False])
575+
assert_series_equal(result, expected1)
576+
538577
def test_nonexistent_raise_coerce(self):
539578
# See issue 13057
540579
from pytz.exceptions import NonExistentTimeError
@@ -629,14 +668,14 @@ def test_localized_at_time_between_time(self):
629668
result = ts_local.at_time(time(10, 0))
630669
expected = ts.at_time(time(10, 0)).tz_localize(self.tzstr(
631670
'US/Eastern'))
632-
tm.assert_series_equal(result, expected)
671+
assert_series_equal(result, expected)
633672
self.assertTrue(self.cmptz(result.index.tz, self.tz('US/Eastern')))
634673

635674
t1, t2 = time(10, 0), time(11, 0)
636675
result = ts_local.between_time(t1, t2)
637676
expected = ts.between_time(t1,
638677
t2).tz_localize(self.tzstr('US/Eastern'))
639-
tm.assert_series_equal(result, expected)
678+
assert_series_equal(result, expected)
640679
self.assertTrue(self.cmptz(result.index.tz, self.tz('US/Eastern')))
641680

642681
def test_string_index_alias_tz_aware(self):
@@ -723,7 +762,7 @@ def test_frame_no_datetime64_dtype(self):
723762
result = df.get_dtype_counts().sort_index()
724763
expected = Series({'datetime64[ns]': 2,
725764
str(tz_expected): 2}).sort_index()
726-
tm.assert_series_equal(result, expected)
765+
assert_series_equal(result, expected)
727766

728767
def test_hongkong_tz_convert(self):
729768
# #1673
@@ -1324,7 +1363,7 @@ def test_append_aware(self):
13241363
exp_index = DatetimeIndex(['2011-01-01 01:00', '2011-01-01 02:00'],
13251364
tz='US/Eastern')
13261365
exp = Series([1, 2], index=exp_index)
1327-
self.assert_series_equal(ts_result, exp)
1366+
assert_series_equal(ts_result, exp)
13281367
self.assertEqual(ts_result.index.tz, rng1.tz)
13291368

13301369
rng1 = date_range('1/1/2011 01:00', periods=1, freq='H', tz='UTC')
@@ -1336,7 +1375,7 @@ def test_append_aware(self):
13361375
exp_index = DatetimeIndex(['2011-01-01 01:00', '2011-01-01 02:00'],
13371376
tz='UTC')
13381377
exp = Series([1, 2], index=exp_index)
1339-
self.assert_series_equal(ts_result, exp)
1378+
assert_series_equal(ts_result, exp)
13401379
utc = rng1.tz
13411380
self.assertEqual(utc, ts_result.index.tz)
13421381

@@ -1352,7 +1391,7 @@ def test_append_aware(self):
13521391
exp_index = Index([Timestamp('1/1/2011 01:00', tz='US/Eastern'),
13531392
Timestamp('1/1/2011 02:00', tz='US/Central')])
13541393
exp = Series([1, 2], index=exp_index)
1355-
self.assert_series_equal(ts_result, exp)
1394+
assert_series_equal(ts_result, exp)
13561395

13571396
def test_append_dst(self):
13581397
rng1 = date_range('1/1/2016 01:00', periods=3, freq='H',
@@ -1368,7 +1407,7 @@ def test_append_dst(self):
13681407
'2016-08-01 02:00', '2016-08-01 03:00'],
13691408
tz='US/Eastern')
13701409
exp = Series([1, 2, 3, 10, 11, 12], index=exp_index)
1371-
tm.assert_series_equal(ts_result, exp)
1410+
assert_series_equal(ts_result, exp)
13721411
self.assertEqual(ts_result.index.tz, rng1.tz)
13731412

13741413
def test_append_aware_naive(self):
@@ -1429,7 +1468,7 @@ def test_arith_utc_convert(self):
14291468
expected = uts1 + uts2
14301469

14311470
self.assertEqual(result.index.tz, pytz.UTC)
1432-
tm.assert_series_equal(result, expected)
1471+
assert_series_equal(result, expected)
14331472

14341473
def test_intersection(self):
14351474
rng = date_range('1/1/2011', periods=100, freq='H', tz='utc')

pandas/tslib.pyx

+9-1
Original file line numberDiff line numberDiff line change
@@ -4155,6 +4155,7 @@ def tz_localize_to_utc(ndarray[int64_t] vals, object tz, object ambiguous=None,
41554155
"""
41564156
cdef:
41574157
ndarray[int64_t] trans, deltas, idx_shifted
4158+
ndarray ambiguous_array
41584159
Py_ssize_t i, idx, pos, ntrans, n = len(vals)
41594160
int64_t *tdata
41604161
int64_t v, left, right
@@ -4190,11 +4191,18 @@ def tz_localize_to_utc(ndarray[int64_t] vals, object tz, object ambiguous=None,
41904191
infer_dst = True
41914192
elif ambiguous == 'NaT':
41924193
fill = True
4194+
elif isinstance(ambiguous, bool):
4195+
is_dst = True
4196+
if ambiguous:
4197+
ambiguous_array = np.ones(len(vals), dtype=bool)
4198+
else:
4199+
ambiguous_array = np.zeros(len(vals), dtype=bool)
41934200
elif hasattr(ambiguous, '__iter__'):
41944201
is_dst = True
41954202
if len(ambiguous) != len(vals):
41964203
raise ValueError(
41974204
"Length of ambiguous bool-array must be the same size as vals")
4205+
ambiguous_array = np.asarray(ambiguous)
41984206

41994207
trans, deltas, typ = _get_dst_info(tz)
42004208

@@ -4286,7 +4294,7 @@ def tz_localize_to_utc(ndarray[int64_t] vals, object tz, object ambiguous=None,
42864294
if infer_dst and dst_hours[i] != NPY_NAT:
42874295
result[i] = dst_hours[i]
42884296
elif is_dst:
4289-
if ambiguous[i]:
4297+
if ambiguous_array[i]:
42904298
result[i] = left
42914299
else:
42924300
result[i] = right

0 commit comments

Comments
 (0)