Skip to content

Commit 48bc59b

Browse files
committed
ENH: Use datetutil.tz.gettz() instead of dateutil.zoneinfo.gettz()
python-dateutil provides two implementations for gettz(), tz.gettz() and zoneinfo.gettz(). The former tries first to use system provided timezone data, where as the later always uses a bundled tarball. Upstreams recommandation for library consumers is only using tz.gettz() (1 & 2). Further more, on system which do not install the zoninfo tarball (e.g. Debian, Gentoo and Fedora) but rely on the system zoneinfo files the direct usage of zoneinfo.gettz() creates problems which result in test failures (3 - 6). For compatibility in pandas code pandas.tslib._dateutil_gettz() should be used. 1 dateutil/dateutil#8 2 dateutil/dateutil#11 3 #9059 4 #8639 5 #10121 6 #9663 Signed-off-by: Justin Lecher <[email protected]>
1 parent f9db166 commit 48bc59b

File tree

7 files changed

+50
-12
lines changed

7 files changed

+50
-12
lines changed

doc/source/whatsnew/v0.17.0.txt

+21-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ New features
2626
Other enhancements
2727
^^^^^^^^^^^^^^^^^^
2828

29+
- Add helper functions to check for OS running on
30+
31+
from pandas.compat import is_platform_windows
32+
if is_platform_window():
33+
pass
34+
35+
- Use dateutil.tz.gettz() after upstream recommandations
36+
37+
python-dateutil provides two implementations of gettz().
38+
"dateutil.tz.gettz()" tries to load zone information from system provided data and fals back to
39+
an included tarball, where as "dateutil.zoneinfo.gettz() loads directly from the tarball. Using the later on systems
40+
which aren't providing included zone informations (e.g. Fedora or Gentoo) breaks (#9059, #8639, #9663 and #10121)
41+
As stated by upstream in https://github.com/dateutil/dateutil/issues/11#issuecomment-70769019 only the former should be
42+
used by library consumers.
43+
44+
For compatibility in pandas following code should be used
45+
46+
from pandas.tslib import _dateutil_gettz as gettz
47+
tz = gettz('Europe/Brussels')
48+
2949
.. _whatsnew_0170.api:
3050

3151
Backwards incompatible API changes
@@ -66,5 +86,4 @@ Bug Fixes
6686
- Bug in ``Timestamp``'s' ``microsecond``, ``quarter``, ``dayofyear``, ``week`` and ``daysinmonth`` properties return ``np.int`` type, not built-in ``int``. (:issue:`10050`)
6787
- Bug in ``NaT`` raises ``AttributeError`` when accessing to ``daysinmonth``, ``dayofweek`` properties. (:issue:`10096`)
6888

69-
70-
89+
- Bug in dateutil.tz.gettz() vs. dateutil.zoneinfo.gettz() usage which creates problems on systems solely rely on systems timezone data (:issue:`9123`, :issue:`9059`, :issue:`8639`, :issue:`9663`, :issue:`10121`)

pandas/compat/__init__.py

+14
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
2727
Other items:
2828
* OrderedDefaultDict
29+
* platform checker
2930
"""
3031
# pylint disable=W0611
3132
import functools
@@ -754,3 +755,16 @@ def __missing__(self, key):
754755
def __reduce__(self): # optional, for pickle support
755756
args = self.default_factory if self.default_factory else tuple()
756757
return type(self), args, None, None, list(self.items())
758+
759+
760+
# https://github.com/pydata/pandas/pull/9123
761+
def is_platform_windows():
762+
return sys.platform == 'win32' or sys.platform == 'cygwin'
763+
764+
765+
def is_platform_linux():
766+
return sys.platform == 'linux2'
767+
768+
769+
def is_platform_mac():
770+
return sys.platform == 'darwin'

pandas/tests/test_series.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5398,7 +5398,8 @@ def test_getitem_setitem_datetime_tz_pytz(self):
53985398
def test_getitem_setitem_datetime_tz_dateutil(self):
53995399
tm._skip_if_no_dateutil();
54005400
from dateutil.tz import tzutc
5401-
from dateutil.zoneinfo import gettz
5401+
from pandas.tslib import _dateutil_gettz as gettz
5402+
54025403
tz = lambda x: tzutc() if x == 'UTC' else gettz(x) # handle special case for utc in dateutil
54035404

54045405
from pandas import date_range

pandas/tseries/tests/test_daterange.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def test_month_range_union_tz_pytz(self):
441441
def test_month_range_union_tz_dateutil(self):
442442
_skip_if_windows_python_3()
443443
tm._skip_if_no_dateutil()
444-
from dateutil.zoneinfo import gettz as timezone
444+
from pandas.tslib import _dateutil_gettz as timezone
445445
tz = timezone('US/Eastern')
446446

447447
early_start = datetime(2011, 1, 1)

pandas/tseries/tests/test_period.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ def test_timestamp_tz_arg(self):
101101
pytz.timezone('Europe/Brussels').normalize(p).tzinfo)
102102

103103
def test_timestamp_tz_arg_dateutil(self):
104-
import dateutil
104+
from pandas.tslib import _dateutil_gettz as gettz
105105
from pandas.tslib import maybe_get_tz
106106
p = Period('1/1/2005', freq='M').to_timestamp(tz=maybe_get_tz('dateutil/Europe/Brussels'))
107-
self.assertEqual(p.tz, dateutil.zoneinfo.gettz('Europe/Brussels'))
107+
self.assertEqual(p.tz, gettz('Europe/Brussels'))
108108

109109
def test_timestamp_tz_arg_dateutil_from_string(self):
110-
import dateutil
110+
from pandas.tslib import _dateutil_gettz as gettz
111111
p = Period('1/1/2005', freq='M').to_timestamp(tz='dateutil/Europe/Brussels')
112-
self.assertEqual(p.tz, dateutil.zoneinfo.gettz('Europe/Brussels'))
112+
self.assertEqual(p.tz, gettz('Europe/Brussels'))
113113

114114
def test_timestamp_nat_tz(self):
115115
t = Period('NaT', freq='M').to_timestamp()

pandas/tseries/tests/test_timeseries.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,9 @@ def test_timestamp_to_datetime_explicit_pytz(self):
417417
def test_timestamp_to_datetime_explicit_dateutil(self):
418418
_skip_if_windows_python_3()
419419
tm._skip_if_no_dateutil()
420-
import dateutil
420+
from pandas.tslib import _dateutil_gettz as gettz
421421
rng = date_range('20090415', '20090519',
422-
tz=dateutil.zoneinfo.gettz('US/Eastern'))
422+
tz=gettz('US/Eastern'))
423423

424424
stamp = rng[0]
425425
dtval = stamp.to_pydatetime()
@@ -1807,7 +1807,7 @@ def test_append_concat_tz_explicit_pytz(self):
18071807
def test_append_concat_tz_dateutil(self):
18081808
# GH 2938
18091809
tm._skip_if_no_dateutil()
1810-
from dateutil.zoneinfo import gettz as timezone
1810+
from pandas.tslib import _dateutil_gettz as timezone
18111811

18121812
rng = date_range('5/8/2012 1:45', periods=10, freq='5T',
18131813
tz='dateutil/US/Eastern')

pandas/tslib.pyx

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ from datetime import time as datetime_time
4141
# dateutil compat
4242
from dateutil.tz import (tzoffset, tzlocal as _dateutil_tzlocal, tzfile as _dateutil_tzfile,
4343
tzutc as _dateutil_tzutc)
44-
from dateutil.zoneinfo import gettz as _dateutil_gettz
44+
from pandas.compat import is_platform_windows
45+
if is_platform_windows():
46+
from dateutil.zoneinfo import gettz as _dateutil_gettz
47+
else:
48+
from dateutil.tz import gettz as _dateutil_gettz
4549

4650
from pytz.tzinfo import BaseTzInfo as _pytz_BaseTzInfo
4751
from pandas.compat import parse_date, string_types, PY3, iteritems

0 commit comments

Comments
 (0)