Skip to content

Commit 7b6a650

Browse files
committed
TST7337: Fix test failures on windows.
Avoid constructing dateutil timezones explicitly because of filename issue. Use dateutil.tz.tzutc() to construct UTC timezone instead of dateutil.tz.gettz('UTC') Update docs to reflect this. Tidy up examples in the timezones section of the docs.
1 parent ba874d5 commit 7b6a650

File tree

8 files changed

+94
-54
lines changed

8 files changed

+94
-54
lines changed

doc/source/timeseries.rst

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
randint = np.random.randint
1313
np.set_printoptions(precision=4, suppress=True)
1414
options.display.max_rows=15
15+
import dateutil
16+
import pytz
1517
from dateutil.relativedelta import relativedelta
1618
from pandas.tseries.api import *
1719
from pandas.tseries.offsets import *
@@ -1266,32 +1268,37 @@ common zones, the names are the same as ``pytz``.
12661268
.. ipython:: python
12671269
12681270
# pytz
1269-
rng_utc = date_range('3/6/2012 00:00', periods=10, freq='D', tz='UTC')
1270-
rng_utc.tz
1271+
rng_pytz = date_range('3/6/2012 00:00', periods=10, freq='D',
1272+
tz='Europe/London')
1273+
rng_pytz.tz
12711274
12721275
# dateutil
1273-
rng_utc_dateutil = date_range('3/6/2012 00:00', periods=10, freq='D',
1274-
tz='dateutil/UTC')
1275-
rng_utc_dateutil.tz
1276+
rng_dateutil = date_range('3/6/2012 00:00', periods=10, freq='D',
1277+
tz='dateutil/Europe/London')
1278+
rng_dateutil.tz
12761279
1277-
You can also construct the timezone explicitly first, which gives you more control over which
1278-
time zone is used:
1280+
# dateutil - utc special case
1281+
rng_utc = date_range('3/6/2012 00:00', periods=10, freq='D',
1282+
tz=dateutil.tz.tzutc())
1283+
rng_utc.tz
1284+
1285+
Note that the ``UTC`` timezone is a special case in ``dateutil`` and should be constructed explicitly
1286+
as an instance of ``dateutil.tz.tzutc``. You can also construct other timezones explicitly first,
1287+
which gives you more control over which time zone is used:
12791288

12801289
.. ipython:: python
12811290
12821291
# pytz
1283-
import pytz
1284-
tz_pytz = pytz.timezone('UTC')
1285-
rng_utc = date_range('3/6/2012 00:00', periods=10, freq='D', tz=tz_pytz)
1286-
rng_utc.tz
1292+
tz_pytz = pytz.timezone('Europe/London')
1293+
rng_pytz = date_range('3/6/2012 00:00', periods=10, freq='D',
1294+
tz=tz_pytz)
1295+
rng_pytz.tz == tz_pytz
12871296
12881297
# dateutil
1289-
import dateutil
1290-
tz_dateutil = dateutil.tz.gettz('UTC')
1291-
rng_utc_dateutil = date_range('3/6/2012 00:00', periods=10, freq='D',
1292-
tz=tz_dateutil)
1293-
rng_utc_dateutil.tz
1294-
1298+
tz_dateutil = dateutil.tz.gettz('Europe/London')
1299+
rng_dateutil = date_range('3/6/2012 00:00', periods=10, freq='D',
1300+
tz=tz_dateutil)
1301+
rng_dateutil.tz == tz_dateutil
12951302
12961303
Timestamps, like Python's ``datetime.datetime`` object can be either time zone
12971304
naive or time zone aware. Naive time series and DatetimeIndex objects can be
@@ -1313,9 +1320,10 @@ tz-aware data to another time zone:
13131320
ts_utc.tz_convert('US/Eastern')
13141321
13151322
.. warning::
1316-
Be very wary of conversions between libraries as ``pytz`` and ``dateutil``
1317-
may have different definitions of the time zones. This is more of a problem for
1318-
unusual timezones than for 'standard' zones like ``US/Eastern``.
1323+
1324+
Be wary of conversions between libraries. For some zones ``pytz`` and ``dateutil`` have different
1325+
definitions of the zone. This is more of a problem for unusual timezones than for
1326+
'standard' zones like ``US/Eastern``.
13191327

13201328
Under the hood, all timestamps are stored in UTC. Scalar values from a
13211329
``DatetimeIndex`` with a time zone will have their fields (day, hour, minute)
@@ -1359,8 +1367,6 @@ TimeSeries, aligning the data on the UTC timestamps:
13591367
result
13601368
result.index
13611369
1362-
.. _timeseries.timedeltas:
1363-
13641370
In some cases, localize cannot determine the DST and non-DST hours when there are
13651371
duplicates. This often happens when reading files that simply duplicate the hours.
13661372
The infer_dst argument in tz_localize will attempt
@@ -1376,6 +1382,8 @@ to determine the right offset.
13761382
rng_hourly_eastern = rng_hourly.tz_localize('US/Eastern', infer_dst=True)
13771383
rng_hourly_eastern.values
13781384
1385+
.. _timeseries.timedeltas:
1386+
13791387
Time Deltas
13801388
-----------
13811389

doc/source/v0.14.1.txt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,9 @@ Enhancements
104104

105105
.. ipython:: python
106106

107-
rng_utc_dateutil = date_range('3/6/2012 00:00',
108-
periods=10,
109-
freq='D',
110-
tz='dateutil/UTC')
111-
rng_utc_dateutil.tz
107+
rng = date_range('3/6/2012 00:00', periods=10, freq='D',
108+
tz='dateutil/Europe/London')
109+
rng.tz
112110

113111
See :ref:`the docs <timeseries.timezone>`.
114112

pandas/tests/test_format.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2946,7 +2946,7 @@ def test_tz_pytz(self):
29462946
def test_tz_dateutil(self):
29472947
_skip_if_no_dateutil()
29482948
import dateutil
2949-
utc = dateutil.tz.gettz('UTC')
2949+
utc = dateutil.tz.tzutc()
29502950

29512951
dt_date = datetime(2013, 1, 2, tzinfo=utc)
29522952
self.assertEqual(str(dt_date), str(Timestamp(dt_date)))

pandas/tests/test_series.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4630,7 +4630,8 @@ def test_getitem_setitem_datetime_tz_pytz(self):
46304630

46314631
def test_getitem_setitem_datetime_tz_dateutil(self):
46324632
_skip_if_no_dateutil();
4633-
from dateutil.tz import gettz as tz
4633+
from dateutil.tz import gettz, tzutc
4634+
tz = lambda x: tzutc() if x == 'UTC' else gettz(x) # handle special case for utc in dateutil
46344635

46354636
from pandas import date_range
46364637
N = 50

pandas/tseries/tests/test_daterange.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pandas.compat import range
33
import pickle
44
import nose
5-
5+
import sys
66
import numpy as np
77

88
from pandas.core.index import Index
@@ -36,6 +36,11 @@ def _skip_if_no_cday():
3636
raise nose.SkipTest("CustomBusinessDay not available.")
3737

3838

39+
def _skip_if_windows_python_3():
40+
if sys.version_info > (3,) and sys.platform == 'win32':
41+
raise nose.SkipTest("not used on python 3/win32")
42+
43+
3944
def eq_gen_range(kwargs, expected):
4045
rng = generate_range(**kwargs)
4146
assert(np.array_equal(list(rng), expected))
@@ -300,7 +305,7 @@ def test_summary_pytz(self):
300305
def test_summary_dateutil(self):
301306
_skip_if_no_dateutil()
302307
import dateutil
303-
bdate_range('1/1/2005', '1/1/2009', tz=dateutil.tz.gettz('UTC')).summary()
308+
bdate_range('1/1/2005', '1/1/2009', tz=dateutil.tz.tzutc()).summary()
304309

305310
def test_misc(self):
306311
end = datetime(2009, 5, 13)
@@ -391,8 +396,10 @@ def test_range_tz_pytz(self):
391396
def test_range_tz_dateutil(self):
392397
# GH 2906
393398
_skip_if_no_dateutil()
394-
from dateutil.tz import gettz as tz
395-
399+
# Use maybe_get_tz to fix filename in tz under dateutil.
400+
from pandas.tslib import maybe_get_tz
401+
tz = lambda x: maybe_get_tz('dateutil/' + x)
402+
396403
start = datetime(2011, 1, 1, tzinfo=tz('US/Eastern'))
397404
end = datetime(2011, 1, 3, tzinfo=tz('US/Eastern'))
398405

@@ -428,6 +435,7 @@ def test_month_range_union_tz_pytz(self):
428435
early_dr.union(late_dr)
429436

430437
def test_month_range_union_tz_dateutil(self):
438+
_skip_if_windows_python_3()
431439
_skip_if_no_dateutil()
432440
from dateutil.tz import gettz as timezone
433441
tz = timezone('US/Eastern')
@@ -633,7 +641,7 @@ def test_summary_pytz(self):
633641
def test_summary_dateutil(self):
634642
_skip_if_no_dateutil()
635643
import dateutil
636-
cdate_range('1/1/2005', '1/1/2009', tz=dateutil.tz.gettz('UTC')).summary()
644+
cdate_range('1/1/2005', '1/1/2009', tz=dateutil.tz.tzutc()).summary()
637645

638646
def test_misc(self):
639647
end = datetime(2009, 5, 13)

pandas/tseries/tests/test_period.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ def test_timestamp_tz_arg(self):
8585

8686
def test_timestamp_tz_arg_dateutil(self):
8787
import dateutil
88-
p = Period('1/1/2005', freq='M').to_timestamp(tz=dateutil.tz.gettz('Europe/Brussels'))
88+
from pandas.tslib import maybe_get_tz
89+
p = Period('1/1/2005', freq='M').to_timestamp(tz=maybe_get_tz('dateutil/Europe/Brussels'))
8990
self.assertEqual(p.tz, dateutil.tz.gettz('Europe/Brussels'))
9091

9192
def test_timestamp_tz_arg_dateutil_from_string(self):

pandas/tseries/tests/test_timeseries.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ def _skip_if_has_locale():
5858
lang, _ = locale.getlocale()
5959
if lang is not None:
6060
raise nose.SkipTest("Specific locale is set {0}".format(lang))
61+
62+
def _skip_if_windows_python_3():
63+
if sys.version_info > (3,) and sys.platform == 'win32':
64+
raise nose.SkipTest("not used on python 3/win32")
65+
66+
def _skip_if_not_windows_python_3():
67+
if sys.version_info < (3,) or sys.platform != 'win32':
68+
raise nose.SkipTest("only run on python 3/win32")
69+
6170

6271
class TestTimeSeriesDuplicates(tm.TestCase):
6372
_multiprocess_can_split_ = True
@@ -406,6 +415,16 @@ def test_timestamp_to_datetime(self):
406415
self.assertEqual(stamp, dtval)
407416
self.assertEqual(stamp.tzinfo, dtval.tzinfo)
408417

418+
def test_timestamp_to_datetime_dateutil(self):
419+
_skip_if_no_pytz()
420+
rng = date_range('20090415', '20090519',
421+
tz='dateutil/US/Eastern')
422+
423+
stamp = rng[0]
424+
dtval = stamp.to_pydatetime()
425+
self.assertEqual(stamp, dtval)
426+
self.assertEqual(stamp.tzinfo, dtval.tzinfo)
427+
409428
def test_timestamp_to_datetime_explicit_pytz(self):
410429
_skip_if_no_pytz()
411430
import pytz
@@ -418,6 +437,7 @@ def test_timestamp_to_datetime_explicit_pytz(self):
418437
self.assertEquals(stamp.tzinfo, dtval.tzinfo)
419438

420439
def test_timestamp_to_datetime_explicit_dateutil(self):
440+
_skip_if_windows_python_3()
421441
_skip_if_no_dateutil()
422442
import dateutil
423443
rng = date_range('20090415', '20090519',
@@ -467,7 +487,7 @@ def _check_rng(rng):
467487
_check_rng(rng_eastern)
468488
_check_rng(rng_utc)
469489

470-
def test_index_convert_to_datetime_array_explicit_dateutil(self):
490+
def test_index_convert_to_datetime_array_dateutil(self):
471491
_skip_if_no_dateutil()
472492
import dateutil
473493

@@ -480,8 +500,8 @@ def _check_rng(rng):
480500
self.assertEquals(x.tzinfo, stamp.tzinfo)
481501

482502
rng = date_range('20090415', '20090519')
483-
rng_eastern = date_range('20090415', '20090519', tz=dateutil.tz.gettz('US/Eastern'))
484-
rng_utc = date_range('20090415', '20090519', tz=dateutil.tz.gettz('UTC'))
503+
rng_eastern = date_range('20090415', '20090519', tz='dateutil/US/Eastern')
504+
rng_utc = date_range('20090415', '20090519', tz=dateutil.tz.tzutc())
485505

486506
_check_rng(rng)
487507
_check_rng(rng_eastern)
@@ -1560,22 +1580,22 @@ def test_to_period_tz_explicit_pytz(self):
15601580
self.assert_(result == expected)
15611581
self.assert_(ts.to_period().equals(xp))
15621582

1563-
def test_to_period_tz_explicit_dateutil(self):
1583+
def test_to_period_tz_dateutil(self):
15641584
_skip_if_no_dateutil()
15651585
import dateutil
15661586
from dateutil.tz import tzlocal
15671587

15681588
xp = date_range('1/1/2000', '4/1/2000').to_period()
15691589

1570-
ts = date_range('1/1/2000', '4/1/2000', tz=dateutil.tz.gettz('US/Eastern'))
1590+
ts = date_range('1/1/2000', '4/1/2000', tz='dateutil/US/Eastern')
15711591

15721592
result = ts.to_period()[0]
15731593
expected = ts[0].to_period()
15741594

15751595
self.assert_(result == expected)
15761596
self.assert_(ts.to_period().equals(xp))
15771597

1578-
ts = date_range('1/1/2000', '4/1/2000', tz=dateutil.tz.gettz('UTC'))
1598+
ts = date_range('1/1/2000', '4/1/2000', tz=dateutil.tz.tzutc())
15791599

15801600
result = ts.to_period()[0]
15811601
expected = ts[0].to_period()
@@ -1793,17 +1813,17 @@ def test_append_concat_tz_explicit_pytz(self):
17931813
appended = rng.append(rng2)
17941814
self.assert_(appended.equals(rng3))
17951815

1796-
def test_append_concat_tz_explicit_dateutil(self):
1816+
def test_append_concat_tz_dateutil(self):
17971817
# GH 2938
17981818
_skip_if_no_dateutil()
17991819
from dateutil.tz import gettz as timezone
18001820

18011821
rng = date_range('5/8/2012 1:45', periods=10, freq='5T',
1802-
tz=timezone('US/Eastern'))
1822+
tz='dateutil/US/Eastern')
18031823
rng2 = date_range('5/8/2012 2:35', periods=10, freq='5T',
1804-
tz=timezone('US/Eastern'))
1824+
tz='dateutil/US/Eastern')
18051825
rng3 = date_range('5/8/2012 1:45', periods=20, freq='5T',
1806-
tz=timezone('US/Eastern'))
1826+
tz='dateutil/US/Eastern')
18071827
ts = Series(np.random.randn(len(rng)), rng)
18081828
df = DataFrame(np.random.randn(len(rng), 4), index=rng)
18091829
ts2 = Series(np.random.randn(len(rng2)), rng2)
@@ -2021,11 +2041,11 @@ def test_period_resample_with_local_timezone_dateutil(self):
20212041
_skip_if_no_dateutil()
20222042
import dateutil
20232043

2024-
local_timezone = dateutil.tz.gettz('America/Los_Angeles')
2044+
local_timezone = 'dateutil/America/Los_Angeles'
20252045

2026-
start = datetime(year=2013, month=11, day=1, hour=0, minute=0, tzinfo=dateutil.tz.gettz('UTC'))
2046+
start = datetime(year=2013, month=11, day=1, hour=0, minute=0, tzinfo=dateutil.tz.tzutc())
20272047
# 1 day later
2028-
end = datetime(year=2013, month=11, day=2, hour=0, minute=0, tzinfo=dateutil.tz.gettz('UTC'))
2048+
end = datetime(year=2013, month=11, day=2, hour=0, minute=0, tzinfo=dateutil.tz.tzutc())
20292049

20302050
index = pd.date_range(start, end, freq='H')
20312051

@@ -2990,13 +3010,13 @@ def compare(x, y):
29903010

29913011
def test_class_ops_dateutil(self):
29923012
_skip_if_no_dateutil()
2993-
from dateutil.tz import gettz as timezone
3013+
from dateutil.tz import tzutc
29943014

29953015
def compare(x,y):
29963016
self.assertEqual(int(np.round(Timestamp(x).value/1e9)), int(np.round(Timestamp(y).value/1e9)))
29973017

29983018
compare(Timestamp.now(),datetime.now())
2999-
compare(Timestamp.now('UTC'), datetime.now(timezone('UTC')))
3019+
compare(Timestamp.now('UTC'), datetime.now(tzutc()))
30003020
compare(Timestamp.utcnow(),datetime.utcnow())
30013021
compare(Timestamp.today(),datetime.today())
30023022

@@ -3149,8 +3169,8 @@ def test_cant_compare_tz_naive_w_aware_explicit_pytz(self):
31493169

31503170
def test_cant_compare_tz_naive_w_aware_dateutil(self):
31513171
_skip_if_no_dateutil()
3152-
from dateutil.tz import gettz
3153-
utc = gettz('UTC')
3172+
from dateutil.tz import tzutc
3173+
utc = tzutc()
31543174
# #1404
31553175
a = Timestamp('3/12/2012')
31563176
b = Timestamp('3/12/2012', tz=utc)

pandas/tseries/tests/test_timezones.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,8 +770,12 @@ def setUp(self):
770770
_skip_if_no_dateutil()
771771

772772
def tz(self, tz):
773-
''' Construct a timezone object from a string. Overridden in subclass to parameterize tests. '''
774-
return dateutil.tz.gettz(tz)
773+
'''
774+
Construct a dateutil timezone.
775+
Use tslib.maybe_get_tz so that we get the filename on the tz right
776+
on windows. See #7337.
777+
'''
778+
return tslib.maybe_get_tz('dateutil/' + tz)
775779

776780
def tzstr(self, tz):
777781
''' Construct a timezone string from a string. Overridden in subclass to parameterize tests. '''

0 commit comments

Comments
 (0)