123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- # -*- coding: utf-8 -*-
- """
- Tests for Series timezone-related methods
- """
- from datetime import datetime
- from dateutil.tz import tzoffset
- import numpy as np
- import pytest
- import pytz
- from pandas._libs.tslibs import conversion, timezones
- from pandas.compat import lrange
- from pandas import DatetimeIndex, Index, NaT, Series, Timestamp
- from pandas.core.indexes.datetimes import date_range
- import pandas.util.testing as tm
- class TestSeriesTimezones(object):
- # -----------------------------------------------------------------
- # Series.tz_localize
- def test_series_tz_localize(self):
- rng = date_range('1/1/2011', periods=100, freq='H')
- ts = Series(1, index=rng)
- result = ts.tz_localize('utc')
- assert result.index.tz.zone == 'UTC'
- # Can't localize if already tz-aware
- rng = date_range('1/1/2011', periods=100, freq='H', tz='utc')
- ts = Series(1, index=rng)
- with pytest.raises(TypeError, match='Already tz-aware'):
- ts.tz_localize('US/Eastern')
- @pytest.mark.filterwarnings('ignore::FutureWarning')
- def test_tz_localize_errors_deprecation(self):
- # GH 22644
- tz = 'Europe/Warsaw'
- n = 60
- rng = date_range(start='2015-03-29 02:00:00', periods=n, freq='min')
- ts = Series(rng)
- with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
- with pytest.raises(ValueError):
- ts.dt.tz_localize(tz, errors='foo')
- # make sure errors='coerce' gets mapped correctly to nonexistent
- result = ts.dt.tz_localize(tz, errors='coerce')
- expected = ts.dt.tz_localize(tz, nonexistent='NaT')
- tm.assert_series_equal(result, expected)
- def test_series_tz_localize_ambiguous_bool(self):
- # make sure that we are correctly accepting bool values as ambiguous
- # GH#14402
- ts = Timestamp('2015-11-01 01:00:03')
- expected0 = Timestamp('2015-11-01 01:00:03-0500', tz='US/Central')
- expected1 = Timestamp('2015-11-01 01:00:03-0600', tz='US/Central')
- ser = Series([ts])
- expected0 = Series([expected0])
- expected1 = Series([expected1])
- with pytest.raises(pytz.AmbiguousTimeError):
- ser.dt.tz_localize('US/Central')
- result = ser.dt.tz_localize('US/Central', ambiguous=True)
- tm.assert_series_equal(result, expected0)
- result = ser.dt.tz_localize('US/Central', ambiguous=[True])
- tm.assert_series_equal(result, expected0)
- result = ser.dt.tz_localize('US/Central', ambiguous=False)
- tm.assert_series_equal(result, expected1)
- result = ser.dt.tz_localize('US/Central', ambiguous=[False])
- tm.assert_series_equal(result, expected1)
- @pytest.mark.parametrize('tz', ['Europe/Warsaw', 'dateutil/Europe/Warsaw'])
- @pytest.mark.parametrize('method, exp', [
- ['shift_forward', '2015-03-29 03:00:00'],
- ['NaT', NaT],
- ['raise', None],
- ['foo', 'invalid']
- ])
- def test_series_tz_localize_nonexistent(self, tz, method, exp):
- # GH 8917
- n = 60
- dti = date_range(start='2015-03-29 02:00:00', periods=n, freq='min')
- s = Series(1, dti)
- if method == 'raise':
- with pytest.raises(pytz.NonExistentTimeError):
- s.tz_localize(tz, nonexistent=method)
- elif exp == 'invalid':
- with pytest.raises(ValueError):
- dti.tz_localize(tz, nonexistent=method)
- else:
- result = s.tz_localize(tz, nonexistent=method)
- expected = Series(1, index=DatetimeIndex([exp] * n, tz=tz))
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize('tzstr', ['US/Eastern', 'dateutil/US/Eastern'])
- def test_series_tz_localize_empty(self, tzstr):
- # GH#2248
- ser = Series()
- ser2 = ser.tz_localize('utc')
- assert ser2.index.tz == pytz.utc
- ser2 = ser.tz_localize(tzstr)
- timezones.tz_compare(ser2.index.tz, timezones.maybe_get_tz(tzstr))
- # -----------------------------------------------------------------
- # Series.tz_convert
- def test_series_tz_convert(self):
- rng = date_range('1/1/2011', periods=200, freq='D', tz='US/Eastern')
- ts = Series(1, index=rng)
- result = ts.tz_convert('Europe/Berlin')
- assert result.index.tz.zone == 'Europe/Berlin'
- # can't convert tz-naive
- rng = date_range('1/1/2011', periods=200, freq='D')
- ts = Series(1, index=rng)
- with pytest.raises(TypeError, match="Cannot convert tz-naive"):
- ts.tz_convert('US/Eastern')
- def test_series_tz_convert_to_utc(self):
- base = DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03'],
- tz='UTC')
- idx1 = base.tz_convert('Asia/Tokyo')[:2]
- idx2 = base.tz_convert('US/Eastern')[1:]
- res = Series([1, 2], index=idx1) + Series([1, 1], index=idx2)
- tm.assert_series_equal(res, Series([np.nan, 3, np.nan], index=base))
- # -----------------------------------------------------------------
- # Series.append
- def test_series_append_aware(self):
- rng1 = date_range('1/1/2011 01:00', periods=1, freq='H',
- tz='US/Eastern')
- rng2 = date_range('1/1/2011 02:00', periods=1, freq='H',
- tz='US/Eastern')
- ser1 = Series([1], index=rng1)
- ser2 = Series([2], index=rng2)
- ts_result = ser1.append(ser2)
- exp_index = DatetimeIndex(['2011-01-01 01:00', '2011-01-01 02:00'],
- tz='US/Eastern')
- exp = Series([1, 2], index=exp_index)
- tm.assert_series_equal(ts_result, exp)
- assert ts_result.index.tz == rng1.tz
- rng1 = date_range('1/1/2011 01:00', periods=1, freq='H', tz='UTC')
- rng2 = date_range('1/1/2011 02:00', periods=1, freq='H', tz='UTC')
- ser1 = Series([1], index=rng1)
- ser2 = Series([2], index=rng2)
- ts_result = ser1.append(ser2)
- exp_index = DatetimeIndex(['2011-01-01 01:00', '2011-01-01 02:00'],
- tz='UTC')
- exp = Series([1, 2], index=exp_index)
- tm.assert_series_equal(ts_result, exp)
- utc = rng1.tz
- assert utc == ts_result.index.tz
- # GH#7795
- # different tz coerces to object dtype, not UTC
- rng1 = date_range('1/1/2011 01:00', periods=1, freq='H',
- tz='US/Eastern')
- rng2 = date_range('1/1/2011 02:00', periods=1, freq='H',
- tz='US/Central')
- ser1 = Series([1], index=rng1)
- ser2 = Series([2], index=rng2)
- ts_result = ser1.append(ser2)
- exp_index = Index([Timestamp('1/1/2011 01:00', tz='US/Eastern'),
- Timestamp('1/1/2011 02:00', tz='US/Central')])
- exp = Series([1, 2], index=exp_index)
- tm.assert_series_equal(ts_result, exp)
- def test_series_append_aware_naive(self):
- rng1 = date_range('1/1/2011 01:00', periods=1, freq='H')
- rng2 = date_range('1/1/2011 02:00', periods=1, freq='H',
- tz='US/Eastern')
- ser1 = Series(np.random.randn(len(rng1)), index=rng1)
- ser2 = Series(np.random.randn(len(rng2)), index=rng2)
- ts_result = ser1.append(ser2)
- expected = ser1.index.astype(object).append(ser2.index.astype(object))
- assert ts_result.index.equals(expected)
- # mixed
- rng1 = date_range('1/1/2011 01:00', periods=1, freq='H')
- rng2 = lrange(100)
- ser1 = Series(np.random.randn(len(rng1)), index=rng1)
- ser2 = Series(np.random.randn(len(rng2)), index=rng2)
- ts_result = ser1.append(ser2)
- expected = ser1.index.astype(object).append(ser2.index)
- assert ts_result.index.equals(expected)
- def test_series_append_dst(self):
- rng1 = date_range('1/1/2016 01:00', periods=3, freq='H',
- tz='US/Eastern')
- rng2 = date_range('8/1/2016 01:00', periods=3, freq='H',
- tz='US/Eastern')
- ser1 = Series([1, 2, 3], index=rng1)
- ser2 = Series([10, 11, 12], index=rng2)
- ts_result = ser1.append(ser2)
- exp_index = DatetimeIndex(['2016-01-01 01:00', '2016-01-01 02:00',
- '2016-01-01 03:00', '2016-08-01 01:00',
- '2016-08-01 02:00', '2016-08-01 03:00'],
- tz='US/Eastern')
- exp = Series([1, 2, 3, 10, 11, 12], index=exp_index)
- tm.assert_series_equal(ts_result, exp)
- assert ts_result.index.tz == rng1.tz
- # -----------------------------------------------------------------
- def test_dateutil_tzoffset_support(self):
- values = [188.5, 328.25]
- tzinfo = tzoffset(None, 7200)
- index = [datetime(2012, 5, 11, 11, tzinfo=tzinfo),
- datetime(2012, 5, 11, 12, tzinfo=tzinfo)]
- series = Series(data=values, index=index)
- assert series.index.tz == tzinfo
- # it works! #2443
- repr(series.index[0])
- @pytest.mark.parametrize('tz', ['US/Eastern', 'dateutil/US/Eastern'])
- def test_tz_aware_asfreq(self, tz):
- dr = date_range('2011-12-01', '2012-07-20', freq='D', tz=tz)
- ser = Series(np.random.randn(len(dr)), index=dr)
- # it works!
- ser.asfreq('T')
- @pytest.mark.parametrize('tz', ['US/Eastern', 'dateutil/US/Eastern'])
- def test_string_index_alias_tz_aware(self, tz):
- rng = date_range('1/1/2000', periods=10, tz=tz)
- ser = Series(np.random.randn(len(rng)), index=rng)
- result = ser['1/3/2000']
- tm.assert_almost_equal(result, ser[2])
- # TODO: De-duplicate with test below
- def test_series_add_tz_mismatch_converts_to_utc_duplicate(self):
- rng = date_range('1/1/2011', periods=10, freq='H', tz='US/Eastern')
- ser = Series(np.random.randn(len(rng)), index=rng)
- ts_moscow = ser.tz_convert('Europe/Moscow')
- result = ser + ts_moscow
- assert result.index.tz is pytz.utc
- result = ts_moscow + ser
- assert result.index.tz is pytz.utc
- def test_series_add_tz_mismatch_converts_to_utc(self):
- rng = date_range('1/1/2011', periods=100, freq='H', tz='utc')
- perm = np.random.permutation(100)[:90]
- ser1 = Series(np.random.randn(90),
- index=rng.take(perm).tz_convert('US/Eastern'))
- perm = np.random.permutation(100)[:90]
- ser2 = Series(np.random.randn(90),
- index=rng.take(perm).tz_convert('Europe/Berlin'))
- result = ser1 + ser2
- uts1 = ser1.tz_convert('utc')
- uts2 = ser2.tz_convert('utc')
- expected = uts1 + uts2
- assert result.index.tz == pytz.UTC
- tm.assert_series_equal(result, expected)
- def test_series_add_aware_naive_raises(self):
- rng = date_range('1/1/2011', periods=10, freq='H')
- ser = Series(np.random.randn(len(rng)), index=rng)
- ser_utc = ser.tz_localize('utc')
- with pytest.raises(Exception):
- ser + ser_utc
- with pytest.raises(Exception):
- ser_utc + ser
- def test_series_align_aware(self):
- idx1 = date_range('2001', periods=5, freq='H', tz='US/Eastern')
- ser = Series(np.random.randn(len(idx1)), index=idx1)
- ser_central = ser.tz_convert('US/Central')
- # # different timezones convert to UTC
- new1, new2 = ser.align(ser_central)
- assert new1.index.tz == pytz.UTC
- assert new2.index.tz == pytz.UTC
- @pytest.mark.parametrize('tzstr', ['US/Eastern', 'dateutil/US/Eastern'])
- def test_localized_at_time_between_time(self, tzstr):
- from datetime import time
- tz = timezones.maybe_get_tz(tzstr)
- rng = date_range('4/16/2012', '5/1/2012', freq='H')
- ts = Series(np.random.randn(len(rng)), index=rng)
- ts_local = ts.tz_localize(tzstr)
- result = ts_local.at_time(time(10, 0))
- expected = ts.at_time(time(10, 0)).tz_localize(tzstr)
- tm.assert_series_equal(result, expected)
- assert timezones.tz_compare(result.index.tz, tz)
- t1, t2 = time(10, 0), time(11, 0)
- result = ts_local.between_time(t1, t2)
- expected = ts.between_time(t1, t2).tz_localize(tzstr)
- tm.assert_series_equal(result, expected)
- assert timezones.tz_compare(result.index.tz, tz)
- @pytest.mark.parametrize('tzstr', ['Europe/Berlin',
- 'dateutil/Europe/Berlin'])
- def test_getitem_pydatetime_tz(self, tzstr):
- tz = timezones.maybe_get_tz(tzstr)
- index = date_range(start='2012-12-24 16:00', end='2012-12-24 18:00',
- freq='H', tz=tzstr)
- ts = Series(index=index, data=index.hour)
- time_pandas = Timestamp('2012-12-24 17:00', tz=tzstr)
- dt = datetime(2012, 12, 24, 17, 0)
- time_datetime = conversion.localize_pydatetime(dt, tz)
- assert ts[time_pandas] == ts[time_datetime]
- def test_series_truncate_datetimeindex_tz(self):
- # GH 9243
- idx = date_range('4/1/2005', '4/30/2005', freq='D', tz='US/Pacific')
- s = Series(range(len(idx)), index=idx)
- result = s.truncate(datetime(2005, 4, 2), datetime(2005, 4, 4))
- expected = Series([1, 2, 3], index=idx[1:4])
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize('copy', [True, False])
- @pytest.mark.parametrize('method, tz', [
- ['tz_localize', None],
- ['tz_convert', 'Europe/Berlin']
- ])
- def test_tz_localize_convert_copy_inplace_mutate(self, copy, method, tz):
- # GH 6326
- result = Series(np.arange(0, 5),
- index=date_range('20131027', periods=5, freq='1H',
- tz=tz))
- getattr(result, method)('UTC', copy=copy)
- expected = Series(np.arange(0, 5),
- index=date_range('20131027', periods=5, freq='1H',
- tz=tz))
- tm.assert_series_equal(result, expected)
|