diff --git a/pandas/conftest.py b/pandas/conftest.py index 90e5ac864e96f..b9d0087b50306 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -1,8 +1,10 @@ import pytest +from distutils.version import LooseVersion import numpy import pandas import pandas.util.testing as tm +import dateutil def pytest_addoption(parser): @@ -65,3 +67,11 @@ def ip(): pytest.importorskip('IPython', minversion="6.0.0") from IPython.core.interactiveshell import InteractiveShell return InteractiveShell() + + +is_dateutil_le_261 = pytest.mark.skipif( + LooseVersion(dateutil.__version__) > '2.6.1', + reason="dateutil api change version") +is_dateutil_gt_261 = pytest.mark.skipif( + LooseVersion(dateutil.__version__) <= '2.6.1', + reason="dateutil stable version") diff --git a/pandas/tests/indexes/datetimes/test_tools.py b/pandas/tests/indexes/datetimes/test_tools.py index f53688fd5c84a..a1287c3102b77 100644 --- a/pandas/tests/indexes/datetimes/test_tools.py +++ b/pandas/tests/indexes/datetimes/test_tools.py @@ -12,6 +12,7 @@ from distutils.version import LooseVersion import pandas as pd +from pandas.conftest import is_dateutil_le_261, is_dateutil_gt_261 from pandas._libs import tslib from pandas._libs.tslibs import parsing from pandas.core.tools import datetimes as tools @@ -996,7 +997,7 @@ def test_dayfirst(self, cache): class TestGuessDatetimeFormat(object): - @pytest.mark.xfail(reason="GH18141 - dateutil > 2.6.1 broken") + @is_dateutil_le_261 def test_guess_datetime_format_for_array(self): tm._skip_if_not_us_locale() expected_format = '%Y-%m-%d %H:%M:%S.%f' @@ -1017,6 +1018,27 @@ def test_guess_datetime_format_for_array(self): [np.nan, np.nan, np.nan], dtype='O')) assert format_for_string_of_nans is None + @is_dateutil_gt_261 + def test_guess_datetime_format_for_array_gt_261(self): + tm._skip_if_not_us_locale() + expected_format = '%Y-%m-%d %H:%M:%S.%f' + dt_string = datetime(2011, 12, 30, 0, 0, 0).strftime(expected_format) + + test_arrays = [ + np.array([dt_string, dt_string, dt_string], dtype='O'), + np.array([np.nan, np.nan, dt_string], dtype='O'), + np.array([dt_string, 'random_string'], dtype='O'), + ] + + for test_array in test_arrays: + assert tools._guess_datetime_format_for_array( + test_array) is None + + format_for_string_of_nans = tools._guess_datetime_format_for_array( + np.array( + [np.nan, np.nan, np.nan], dtype='O')) + assert format_for_string_of_nans is None + class TestToDatetimeInferFormat(object): diff --git a/pandas/tests/scalar/test_parsing.py b/pandas/tests/scalar/test_parsing.py index 54ae84b678a94..70961755ceec9 100644 --- a/pandas/tests/scalar/test_parsing.py +++ b/pandas/tests/scalar/test_parsing.py @@ -3,14 +3,12 @@ Tests for Timestamp parsing, aimed at pandas/_libs/tslibs/parsing.pyx """ from datetime import datetime - import numpy as np import pytest from dateutil.parser import parse - +from pandas.conftest import is_dateutil_le_261, is_dateutil_gt_261 from pandas import compat from pandas.util import testing as tm - from pandas._libs.tslibs import parsing @@ -68,7 +66,7 @@ def test_parsers_monthfreq(self): class TestGuessDatetimeFormat(object): - @pytest.mark.xfail(reason="GH18141 - dateutil > 2.6.1 broken") + @is_dateutil_le_261 @pytest.mark.parametrize( "string, format", [ @@ -86,7 +84,20 @@ def test_guess_datetime_format_with_parseable_formats( result = parsing._guess_datetime_format(string) assert result == format - @pytest.mark.xfail(reason="GH18141 - dateutil > 2.6.1 broken") + @is_dateutil_gt_261 + @pytest.mark.parametrize( + "string", + ['20111230', '2011-12-30', '30-12-2011', + '2011-12-30 00:00:00', '2011-12-30T00:00:00', + '2011-12-30 00:00:00.000000']) + def test_guess_datetime_format_with_parseable_formats_gt_261( + self, string): + tm._skip_if_not_us_locale() + + result = parsing._guess_datetime_format(string) + assert result is None + + @is_dateutil_le_261 @pytest.mark.parametrize( "dayfirst, expected", [ @@ -98,7 +109,16 @@ def test_guess_datetime_format_with_dayfirst(self, dayfirst, expected): ambiguous_string, dayfirst=dayfirst) assert result == expected - @pytest.mark.xfail(reason="GH18141 - dateutil > 2.6.1 broken") + @is_dateutil_gt_261 + @pytest.mark.parametrize( + "dayfirst", [True, False]) + def test_guess_datetime_format_with_dayfirst_gt_261(self, dayfirst): + ambiguous_string = '01/01/2011' + result = parsing._guess_datetime_format( + ambiguous_string, dayfirst=dayfirst) + assert result is None + + @is_dateutil_le_261 @pytest.mark.parametrize( "string, format", [ @@ -114,6 +134,22 @@ def test_guess_datetime_format_with_locale_specific_formats( result = parsing._guess_datetime_format(string) assert result == format + @is_dateutil_gt_261 + @pytest.mark.parametrize( + "string", + [ + '30/Dec/2011', + '30/December/2011', + '30/Dec/2011 00:00:00']) + def test_guess_datetime_format_with_locale_specific_formats_gt_261( + self, string): + # The month names will vary depending on the locale, in which + # case these wont be parsed properly (dateutil can't parse them) + tm._skip_if_has_locale() + + result = parsing._guess_datetime_format(string) + assert result is None + def test_guess_datetime_format_invalid_inputs(self): # A datetime string must include a year, month and a day for it # to be guessable, in addition to being a string that looks like @@ -132,7 +168,7 @@ def test_guess_datetime_format_invalid_inputs(self): for invalid_dt in invalid_dts: assert parsing._guess_datetime_format(invalid_dt) is None - @pytest.mark.xfail(reason="GH18141 - dateutil > 2.6.1 broken") + @is_dateutil_le_261 @pytest.mark.parametrize( "string, format", [ @@ -147,6 +183,21 @@ def test_guess_datetime_format_nopadding(self, string, format): result = parsing._guess_datetime_format(string) assert result == format + @is_dateutil_gt_261 + @pytest.mark.parametrize( + "string", + [ + '2011-1-1', + '30-1-2011', + '1/1/2011', + '2011-1-1 00:00:00', + '2011-1-1 0:0:0', + '2011-1-3T00:00:0']) + def test_guess_datetime_format_nopadding_gt_261(self, string): + # GH 11142 + result = parsing._guess_datetime_format(string) + assert result is None + class TestArrayToDatetime(object): def test_try_parse_dates(self):