|
4 | 4 |
|
5 | 5 | import numpy as np
|
6 | 6 | import pytz
|
7 |
| - |
| 7 | +from distutils.version import LooseVersion |
8 | 8 | from pandas.types.dtypes import DatetimeTZDtype
|
9 | 9 | from pandas import (Index, Series, DataFrame, isnull, Timestamp)
|
10 | 10 |
|
@@ -518,8 +518,12 @@ def f():
|
518 | 518 |
|
519 | 519 | times = date_range("2013-10-26 23:00", "2013-10-27 01:00", freq="H",
|
520 | 520 | tz=tz, ambiguous='infer')
|
521 |
| - self.assertEqual(times[0], Timestamp('2013-10-26 23:00', tz=tz)) |
522 |
| - self.assertEqual(times[-1], Timestamp('2013-10-27 01:00', tz=tz)) |
| 521 | + self.assertEqual(times[0], Timestamp('2013-10-26 23:00', tz=tz, |
| 522 | + freq="H")) |
| 523 | + if dateutil.__version__ != LooseVersion('2.6.0'): |
| 524 | + # GH 14621 |
| 525 | + self.assertEqual(times[-1], Timestamp('2013-10-27 01:00', tz=tz, |
| 526 | + freq="H")) |
523 | 527 |
|
524 | 528 | def test_ambiguous_nat(self):
|
525 | 529 | tz = self.tz('US/Eastern')
|
@@ -1163,6 +1167,85 @@ class TestTimeZones(tm.TestCase):
|
1163 | 1167 | def setUp(self):
|
1164 | 1168 | tm._skip_if_no_pytz()
|
1165 | 1169 |
|
| 1170 | + def test_replace(self): |
| 1171 | + # GH 14621 |
| 1172 | + # GH 7825 |
| 1173 | + # replacing datetime components with and w/o presence of a timezone |
| 1174 | + dt = Timestamp('2016-01-01 09:00:00') |
| 1175 | + result = dt.replace(hour=0) |
| 1176 | + expected = Timestamp('2016-01-01 00:00:00') |
| 1177 | + self.assertEqual(result, expected) |
| 1178 | + |
| 1179 | + for tz in self.timezones: |
| 1180 | + dt = Timestamp('2016-01-01 09:00:00', tz=tz) |
| 1181 | + result = dt.replace(hour=0) |
| 1182 | + expected = Timestamp('2016-01-01 00:00:00', tz=tz) |
| 1183 | + self.assertEqual(result, expected) |
| 1184 | + |
| 1185 | + # we preserve nanoseconds |
| 1186 | + dt = Timestamp('2016-01-01 09:00:00.000000123', tz=tz) |
| 1187 | + result = dt.replace(hour=0) |
| 1188 | + expected = Timestamp('2016-01-01 00:00:00.000000123', tz=tz) |
| 1189 | + self.assertEqual(result, expected) |
| 1190 | + |
| 1191 | + # test all |
| 1192 | + dt = Timestamp('2016-01-01 09:00:00.000000123', tz=tz) |
| 1193 | + result = dt.replace(year=2015, month=2, day=2, hour=0, minute=5, |
| 1194 | + second=5, microsecond=5, nanosecond=5) |
| 1195 | + expected = Timestamp('2015-02-02 00:05:05.000005005', tz=tz) |
| 1196 | + self.assertEqual(result, expected) |
| 1197 | + |
| 1198 | + # error |
| 1199 | + def f(): |
| 1200 | + dt.replace(foo=5) |
| 1201 | + self.assertRaises(ValueError, f) |
| 1202 | + |
| 1203 | + def f(): |
| 1204 | + dt.replace(hour=0.1) |
| 1205 | + self.assertRaises(ValueError, f) |
| 1206 | + |
| 1207 | + # assert conversion to naive is the same as replacing tzinfo with None |
| 1208 | + dt = Timestamp('2013-11-03 01:59:59.999999-0400', tz='US/Eastern') |
| 1209 | + self.assertEqual(dt.tz_localize(None), dt.replace(tzinfo=None)) |
| 1210 | + |
| 1211 | + def test_ambiguous_compat(self): |
| 1212 | + # validate that pytz and dateutil are compat for dst |
| 1213 | + # when the transition happens |
| 1214 | + tm._skip_if_no_dateutil() |
| 1215 | + tm._skip_if_no_pytz() |
| 1216 | + |
| 1217 | + pytz_zone = 'Europe/London' |
| 1218 | + dateutil_zone = 'dateutil/Europe/London' |
| 1219 | + result_pytz = (Timestamp('2013-10-27 01:00:00') |
| 1220 | + .tz_localize(pytz_zone, ambiguous=0)) |
| 1221 | + result_dateutil = (Timestamp('2013-10-27 01:00:00') |
| 1222 | + .tz_localize(dateutil_zone, ambiguous=0)) |
| 1223 | + self.assertEqual(result_pytz.value, result_dateutil.value) |
| 1224 | + self.assertEqual(result_pytz.value, 1382835600000000000) |
| 1225 | + |
| 1226 | + # dateutil 2.6 buggy w.r.t. ambiguous=0 |
| 1227 | + if dateutil.__version__ != LooseVersion('2.6.0'): |
| 1228 | + # GH 14621 |
| 1229 | + # https://github.com/dateutil/dateutil/issues/321 |
| 1230 | + self.assertEqual(result_pytz.to_pydatetime().tzname(), |
| 1231 | + result_dateutil.to_pydatetime().tzname()) |
| 1232 | + self.assertEqual(str(result_pytz), str(result_dateutil)) |
| 1233 | + |
| 1234 | + # 1 hour difference |
| 1235 | + result_pytz = (Timestamp('2013-10-27 01:00:00') |
| 1236 | + .tz_localize(pytz_zone, ambiguous=1)) |
| 1237 | + result_dateutil = (Timestamp('2013-10-27 01:00:00') |
| 1238 | + .tz_localize(dateutil_zone, ambiguous=1)) |
| 1239 | + self.assertEqual(result_pytz.value, result_dateutil.value) |
| 1240 | + self.assertEqual(result_pytz.value, 1382832000000000000) |
| 1241 | + |
| 1242 | + # dateutil < 2.6 is buggy w.r.t. ambiguous timezones |
| 1243 | + if dateutil.__version__ > LooseVersion('2.5.3'): |
| 1244 | + # GH 14621 |
| 1245 | + self.assertEqual(str(result_pytz), str(result_dateutil)) |
| 1246 | + self.assertEqual(result_pytz.to_pydatetime().tzname(), |
| 1247 | + result_dateutil.to_pydatetime().tzname()) |
| 1248 | + |
1166 | 1249 | def test_index_equals_with_tz(self):
|
1167 | 1250 | left = date_range('1/1/2011', periods=100, freq='H', tz='utc')
|
1168 | 1251 | right = date_range('1/1/2011', periods=100, freq='H', tz='US/Eastern')
|
|
0 commit comments