From 4281f16001ed5d861538c684d2728f93f0eba2d2 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 16:16:56 +0200 Subject: [PATCH 01/19] DEPR: Deprecate parse_date_time in pandas.io.date_converters and update tests --- doc/source/user_guide/io.rst | 2 +- pandas/io/date_converters.py | 23 +++++++++++++++++++--- pandas/tests/io/parser/test_parse_dates.py | 6 +++--- pandas/tests/io/test_date_converters.py | 7 ++++--- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index d4be9d802d697..aa6529b3a76d6 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -927,7 +927,7 @@ take full advantage of the flexibility of the date parsing API: .. ipython:: python df = pd.read_csv('tmp.csv', header=None, parse_dates=date_spec, - date_parser=pd.io.date_converters.parse_date_time) + date_parser=pd.to_datetime) df Pandas will try to call the ``date_parser`` function in three different ways. If diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index 07919dbda63ae..9e3f0a9d1b807 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -1,13 +1,30 @@ """This module is designed for community supported date conversion functions""" +import warnings + import numpy as np from pandas._libs.tslibs import parsing +from pandas import to_datetime + def parse_date_time(date_col, time_col): - date_col = _maybe_cast(date_col) - time_col = _maybe_cast(time_col) - return parsing.try_parse_date_and_time(date_col, time_col) + """Convert separate columns with dates and times into a single datetime column + + .. deprecated:: 1.1.0 + Use pd.to_datetime(date_col + " " + time_col) instead to get a Pandas Series. + Use pd.to_datetime(date_col + " " + time_col).to_pydatetime() instead to get + a Numpy array. + """ + warnings.warn( + """ + Use pd.to_datetime(date_col + " " + time_col) instead to get a Pandas Series. + Use pd.to_datetime(date_col + " " + time_col).to_pydatetime() instead to get a Numpy array. +""", # noqa: E501 + FutureWarning, + stacklevel=2, + ) + return to_datetime(date_col + " " + time_col).to_pydatetime() def parse_date_fields(year_col, month_col, day_col): diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index ed947755e3419..3262e29b1a83e 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -385,7 +385,7 @@ def test_multiple_date_cols_int_cast(all_parsers): result = parser.read_csv( StringIO(data), header=None, - date_parser=conv.parse_date_time, + date_parser=pd.to_datetime, parse_dates=parse_dates, prefix="X", ) @@ -1178,7 +1178,7 @@ def test_parse_date_time_multi_level_column_name(all_parsers): StringIO(data), header=[0, 1], parse_dates={"date_time": [0, 1]}, - date_parser=conv.parse_date_time, + date_parser=pd.to_datetime, ) expected_data = [ @@ -1263,7 +1263,7 @@ def test_parse_date_time_multi_level_column_name(all_parsers): ) def test_parse_date_time(all_parsers, data, kwargs, expected): parser = all_parsers - result = parser.read_csv(StringIO(data), date_parser=conv.parse_date_time, **kwargs) + result = parser.read_csv(StringIO(data), date_parser=pd.to_datetime, **kwargs) # Python can sometimes be flaky about how # the aggregated columns are entered, so diff --git a/pandas/tests/io/test_date_converters.py b/pandas/tests/io/test_date_converters.py index cdb8eca02a3e5..27b2e6a409629 100644 --- a/pandas/tests/io/test_date_converters.py +++ b/pandas/tests/io/test_date_converters.py @@ -8,12 +8,13 @@ def test_parse_date_time(): + dates = np.array(["2007/1/3", "2008/2/4"], dtype=object) times = np.array(["05:07:09", "06:08:00"], dtype=object) expected = np.array([datetime(2007, 1, 3, 5, 7, 9), datetime(2008, 2, 4, 6, 8, 0)]) - - result = conv.parse_date_time(dates, times) - tm.assert_numpy_array_equal(result, expected) + with tm.assert_produces_warning(FutureWarning): + result = conv.parse_date_time(dates, times) + tm.assert_numpy_array_equal(result, expected) def test_parse_date_fields(): From 852d4d9e8aff76eddb0dac2b24c32ee624fb3bc1 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 17:37:25 +0200 Subject: [PATCH 02/19] DEPR: Deprecate parse_date_fields in pandas.io.date_converters and update tests --- pandas/io/date_converters.py | 24 ++++++++++++++++++---- pandas/tests/io/parser/test_parse_dates.py | 2 +- pandas/tests/io/test_date_converters.py | 7 ++++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index 9e3f0a9d1b807..a13dab6e5a492 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -28,10 +28,26 @@ def parse_date_time(date_col, time_col): def parse_date_fields(year_col, month_col, day_col): - year_col = _maybe_cast(year_col) - month_col = _maybe_cast(month_col) - day_col = _maybe_cast(day_col) - return parsing.try_parse_year_month_day(year_col, month_col, day_col) + """Convert separate columns with years, months and days into a single date column + + .. deprecated:: 1.1.0 + Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) + instead to get a Pandas Series. + Use ser = pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) + and np.array([s.to_pydatetime() for s in ser]) instead to get a Numpy array. + """ + warnings.warn( + """ + Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) instead to get a Pandas Series. + Use ser = pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) and + np.array([s.to_pydatetime() for s in ser]) instead to get a Numpy array. +""", # noqa: E501 + FutureWarning, + stacklevel=2, + ) + + ser = to_datetime({"year": year_col, "month": month_col, "day": day_col}) + return np.array([s.to_pydatetime() for s in ser]) def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_col): diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index 3262e29b1a83e..bc63fcb860fda 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -1279,7 +1279,7 @@ def test_parse_date_fields(all_parsers): StringIO(data), header=0, parse_dates={"ymd": [0, 1, 2]}, - date_parser=conv.parse_date_fields, + date_parser=pd.to_datetime, ) expected = DataFrame( diff --git a/pandas/tests/io/test_date_converters.py b/pandas/tests/io/test_date_converters.py index 27b2e6a409629..1d4e93debea75 100644 --- a/pandas/tests/io/test_date_converters.py +++ b/pandas/tests/io/test_date_converters.py @@ -21,10 +21,11 @@ def test_parse_date_fields(): days = np.array([3, 4]) months = np.array([1, 2]) years = np.array([2007, 2008]) - result = conv.parse_date_fields(years, months, days) - expected = np.array([datetime(2007, 1, 3), datetime(2008, 2, 4)]) - tm.assert_numpy_array_equal(result, expected) + + with tm.assert_produces_warning(FutureWarning): + result = conv.parse_date_fields(years, months, days) + tm.assert_numpy_array_equal(result, expected) def test_parse_all_fields(): From eed8f16b54f873f84007104abd4c76f62d2416eb Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 17:49:05 +0200 Subject: [PATCH 03/19] DEPR: Deprecate parse_all_fields in pandas.io.date_converters and update tests --- pandas/io/date_converters.py | 45 +++++++++++++++++----- pandas/tests/io/parser/test_parse_dates.py | 8 ++-- pandas/tests/io/test_date_converters.py | 7 ++-- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index a13dab6e5a492..3be8a0f4e7992 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -3,8 +3,6 @@ import numpy as np -from pandas._libs.tslibs import parsing - from pandas import to_datetime @@ -51,16 +49,43 @@ def parse_date_fields(year_col, month_col, day_col): def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_col): - year_col = _maybe_cast(year_col) - month_col = _maybe_cast(month_col) - day_col = _maybe_cast(day_col) - hour_col = _maybe_cast(hour_col) - minute_col = _maybe_cast(minute_col) - second_col = _maybe_cast(second_col) - return parsing.try_parse_datetime_components( - year_col, month_col, day_col, hour_col, minute_col, second_col + """Convert separate columns with years, months, days, hours, minutes and seconds + into a single datetime column + + .. deprecated:: 1.1.0 + Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, + "hour": hour_col, "minute": minute_col, second": second_col}) instead to get + a Pandas Series. + Use ser = pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, + "hour": hour_col, "minute": minute_col, second": second_col}) and + np.array([s.to_pydatetime() for s in ser]) instead to get a Numpy array. + """ + + warnings.warn( + """ + Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, + "hour": hour_col, "minute": minute_col, second": second_col}) instead to get a Pandas Series. + Use ser = pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, + "hour": hour_col, "minute": minute_col, second": second_col}) and + np.array([s.to_pydatetime() for s in ser]) instead to get a Numpy array. +""", # noqa: E501 + FutureWarning, + stacklevel=2, ) + ser = to_datetime( + { + "year": year_col, + "month": month_col, + "day": day_col, + "hour": hour_col, + "minute": minute_col, + "second": second_col, + } + ) + + return np.array([s.to_pydatetime() for s in ser]) + def generic_parser(parse_func, *cols): N = _check_columns(cols) diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index bc63fcb860fda..2d362d949756e 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -23,8 +23,6 @@ import pandas._testing as tm from pandas.core.indexes.datetimes import date_range -import pandas.io.date_converters as conv - # constant _DEFAULT_DATETIME = datetime(1, 1, 1) @@ -1290,6 +1288,7 @@ def test_parse_date_fields(all_parsers): def test_parse_date_all_fields(all_parsers): + parser = all_parsers data = """\ year,month,day,hour,minute,second,a,b @@ -1299,7 +1298,7 @@ def test_parse_date_all_fields(all_parsers): result = parser.read_csv( StringIO(data), header=0, - date_parser=conv.parse_all_fields, + date_parser=lambda x: pd.to_datetime(x, format="%Y %m %d %H %M %S"), parse_dates={"ymdHMS": [0, 1, 2, 3, 4, 5]}, ) expected = DataFrame( @@ -1322,7 +1321,8 @@ def test_datetime_fractional_seconds(all_parsers): result = parser.read_csv( StringIO(data), header=0, - date_parser=conv.parse_all_fields, + # date_parser=conv.parse_all_fields, + date_parser=lambda x: pd.to_datetime(x, format="%Y %m %d %H %M %S.%f"), parse_dates={"ymdHMS": [0, 1, 2, 3, 4, 5]}, ) expected = DataFrame( diff --git a/pandas/tests/io/test_date_converters.py b/pandas/tests/io/test_date_converters.py index 1d4e93debea75..4fb53decfd887 100644 --- a/pandas/tests/io/test_date_converters.py +++ b/pandas/tests/io/test_date_converters.py @@ -36,7 +36,8 @@ def test_parse_all_fields(): days = np.array([3, 4]) years = np.array([2007, 2008]) months = np.array([1, 2]) - - result = conv.parse_all_fields(years, months, days, hours, minutes, seconds) expected = np.array([datetime(2007, 1, 3, 5, 7, 9), datetime(2008, 2, 4, 6, 8, 0)]) - tm.assert_numpy_array_equal(result, expected) + + with tm.assert_produces_warning(FutureWarning): + result = conv.parse_all_fields(years, months, days, hours, minutes, seconds) + tm.assert_numpy_array_equal(result, expected) From 65ec57007b31055547eaa05425a799bf7490e2a5 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 20:08:57 +0200 Subject: [PATCH 04/19] DEPR: Deprecate generic_parser in pandas.io.date_converters --- pandas/io/date_converters.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index 3be8a0f4e7992..88ba1764dbc02 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -88,6 +88,20 @@ def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_ def generic_parser(parse_func, *cols): + """Parse single row of values into a datetime + + .. deprecated:: 1.1.0 + Use pd.to_datetime. + """ + + warnings.warn( + """ + Use pd.to_datetime instead. +""", # noqa: E501 + FutureWarning, + stacklevel=2, + ) + N = _check_columns(cols) results = np.empty(N, dtype=object) @@ -98,12 +112,6 @@ def generic_parser(parse_func, *cols): return results -def _maybe_cast(arr): - if not arr.dtype.type == np.object_: - arr = np.array(arr, dtype=object) - return arr - - def _check_columns(cols): if not len(cols): raise AssertionError("There must be at least 1 column") From 344e5de336e6c4dc84fef2b9f1af9a29794f2c06 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 20:19:07 +0200 Subject: [PATCH 05/19] DOC: Update docstrings --- pandas/io/date_converters.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index 88ba1764dbc02..55777f77e4296 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -7,7 +7,8 @@ def parse_date_time(date_col, time_col): - """Convert separate columns with dates and times into a single datetime column + """ + Parse columns with dates and times into a single datetime column. .. deprecated:: 1.1.0 Use pd.to_datetime(date_col + " " + time_col) instead to get a Pandas Series. @@ -26,7 +27,8 @@ def parse_date_time(date_col, time_col): def parse_date_fields(year_col, month_col, day_col): - """Convert separate columns with years, months and days into a single date column + """ + Parse columns with years, months and days into a single date column. .. deprecated:: 1.1.0 Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) @@ -49,8 +51,8 @@ def parse_date_fields(year_col, month_col, day_col): def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_col): - """Convert separate columns with years, months, days, hours, minutes and seconds - into a single datetime column + """ + Parse columns with datetime information into a single datetime column. .. deprecated:: 1.1.0 Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, @@ -88,10 +90,11 @@ def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_ def generic_parser(parse_func, *cols): - """Parse single row of values into a datetime + """ + Use dateparser to parse columns with data information into a single datetime column. .. deprecated:: 1.1.0 - Use pd.to_datetime. + Use pd.to_datetime instead. """ warnings.warn( From 04d3416d3c3731cb9e1e4d6a43b468fd00adba87 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 20:32:56 +0200 Subject: [PATCH 06/19] DOC: remove mentions of the generic_parser functionality in the documenation --- doc/source/user_guide/io.rst | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index aa6529b3a76d6..c73ce4cc349eb 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -939,11 +939,6 @@ an exception is raised, the next one is tried: 2. If #1 fails, ``date_parser`` is called with all the columns concatenated row-wise into a single array (e.g., ``date_parser(['2013 1', '2013 2'])``). -3. If #2 fails, ``date_parser`` is called once for every row with one or more - string arguments from the columns indicated with `parse_dates` - (e.g., ``date_parser('2013', '1')`` for the first row, ``date_parser('2013', '2')`` - for the second, etc.). - Note that performance-wise, you should try these methods of parsing dates in order: 1. Try to infer the format using ``infer_datetime_format=True`` (see section below). @@ -955,14 +950,6 @@ Note that performance-wise, you should try these methods of parsing dates in ord For optimal performance, this should be vectorized, i.e., it should accept arrays as arguments. -You can explore the date parsing functionality in -`date_converters.py `__ -and add your own. We would love to turn this module into a community supported -set of date/time parsers. To get you started, ``date_converters.py`` contains -functions to parse dual date and time columns, year/month/day columns, -and year/month/day/hour/minute/second columns. It also contains a -``generic_parser`` function so you can curry it with a function that deals with -a single date rather than the entire array. .. ipython:: python :suppress: From 3df6bf975542950b54592caf4feea8f6c9881eb4 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 20:47:46 +0200 Subject: [PATCH 07/19] CLN: remove date_parser argument from test where it is not necessary --- pandas/tests/io/parser/test_parse_dates.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index 2d362d949756e..928cf11650722 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -381,11 +381,7 @@ def test_multiple_date_cols_int_cast(all_parsers): parser = all_parsers result = parser.read_csv( - StringIO(data), - header=None, - date_parser=pd.to_datetime, - parse_dates=parse_dates, - prefix="X", + StringIO(data), header=None, parse_dates=parse_dates, prefix="X", ) expected = DataFrame( [ @@ -1173,10 +1169,7 @@ def test_parse_date_time_multi_level_column_name(all_parsers): """ parser = all_parsers result = parser.read_csv( - StringIO(data), - header=[0, 1], - parse_dates={"date_time": [0, 1]}, - date_parser=pd.to_datetime, + StringIO(data), header=[0, 1], parse_dates={"date_time": [0, 1]}, ) expected_data = [ @@ -1261,7 +1254,7 @@ def test_parse_date_time_multi_level_column_name(all_parsers): ) def test_parse_date_time(all_parsers, data, kwargs, expected): parser = all_parsers - result = parser.read_csv(StringIO(data), date_parser=pd.to_datetime, **kwargs) + result = parser.read_csv(StringIO(data), **kwargs) # Python can sometimes be flaky about how # the aggregated columns are entered, so @@ -1273,12 +1266,7 @@ def test_parse_date_time(all_parsers, data, kwargs, expected): def test_parse_date_fields(all_parsers): parser = all_parsers data = "year,month,day,a\n2001,01,10,10.\n2001,02,1,11." - result = parser.read_csv( - StringIO(data), - header=0, - parse_dates={"ymd": [0, 1, 2]}, - date_parser=pd.to_datetime, - ) + result = parser.read_csv(StringIO(data), header=0, parse_dates={"ymd": [0, 1, 2]},) expected = DataFrame( [[datetime(2001, 1, 10), 10.0], [datetime(2001, 2, 1), 11.0]], From c995111b4e8818b412d41172102a5c693e878c0f Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 22:41:52 +0200 Subject: [PATCH 08/19] TYP: Add MutableMapping to type hinting for pd.to_datetime --- pandas/core/tools/datetimes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/tools/datetimes.py b/pandas/core/tools/datetimes.py index 0adab143f6052..1b80dff2ff1a8 100644 --- a/pandas/core/tools/datetimes.py +++ b/pandas/core/tools/datetimes.py @@ -6,6 +6,7 @@ TYPE_CHECKING, Callable, List, + MutableMapping, Optional, Tuple, TypeVar, @@ -59,7 +60,7 @@ # --------------------------------------------------------------------- # types used in annotations -ArrayConvertible = Union[List, Tuple, ArrayLike, "Series"] +ArrayConvertible = Union[List, Tuple, ArrayLike, "Series", MutableMapping] Scalar = Union[int, float, str] DatetimeScalar = TypeVar("DatetimeScalar", Scalar, datetime) DatetimeScalarOrArrayConvertible = Union[DatetimeScalar, ArrayConvertible] From ef02e73a0dba366c7ff7f4d4cc5cf9039b40b55b Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 15 Aug 2020 23:30:04 +0200 Subject: [PATCH 09/19] ENH: Add overloading to pd.to_datetime for MutableMapping --- pandas/core/tools/datetimes.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pandas/core/tools/datetimes.py b/pandas/core/tools/datetimes.py index 1b80dff2ff1a8..1eb8ee4434d39 100644 --- a/pandas/core/tools/datetimes.py +++ b/pandas/core/tools/datetimes.py @@ -585,6 +585,23 @@ def to_datetime( ... +@overload +def to_datetime( + arg: MutableMapping, + errors: str = ..., + dayfirst: bool = ..., + yearfirst: bool = ..., + utc: Optional[bool] = ..., + format: Optional[str] = ..., + exact: bool = ..., + unit: Optional[str] = ..., + infer_datetime_format: bool = ..., + origin=..., + cache: bool = ..., +) -> "Series": + ... + + @overload def to_datetime( arg: Union[List, Tuple], From 3376f49e75854a3f5bbd7dae9f79645baa9a2a6f Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Tue, 18 Aug 2020 21:37:33 +0200 Subject: [PATCH 10/19] TST: Update tests where generic_parser is used --- pandas/tests/io/parser/test_parse_dates.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index 928cf11650722..1480fc8353f99 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -802,7 +802,7 @@ def test_parse_dates_custom_euro_format(all_parsers, kwargs): tm.assert_frame_equal(df, expected) else: msg = "got an unexpected keyword argument 'day_first'" - with pytest.raises(TypeError, match=msg): + with pytest.raises(TypeError, match=msg), pytest.warns(FutureWarning): parser.read_csv( StringIO(data), names=["time", "Q", "NTU"], @@ -1327,12 +1327,13 @@ def test_generic(all_parsers): parser = all_parsers data = "year,month,day,a\n2001,01,10,10.\n2001,02,1,11." - result = parser.read_csv( - StringIO(data), - header=0, - parse_dates={"ym": [0, 1]}, - date_parser=lambda y, m: date(year=int(y), month=int(m), day=1), - ) + with pytest.warns(FutureWarning): + result = parser.read_csv( + StringIO(data), + header=0, + parse_dates={"ym": [0, 1]}, + date_parser=lambda y, m: date(year=int(y), month=int(m), day=1), + ) expected = DataFrame( [[date(2001, 1, 1), 10, 10.0], [date(2001, 2, 1), 1, 11.0]], columns=["ym", "day", "a"], From 71297cf999eb0e2b95f399475746bc7ac19aef63 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Tue, 18 Aug 2020 22:14:50 +0200 Subject: [PATCH 11/19] TST: Update tests for generic_parser in line with pandas styleguide --- pandas/tests/io/parser/test_parse_dates.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index 1480fc8353f99..d5eae829f67f0 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -772,6 +772,7 @@ def test_multi_index_parse_dates(all_parsers, index_col): tm.assert_frame_equal(result, expected) +@pytest.mark.filterwarnings("ignore::FutureWarning") @pytest.mark.parametrize("kwargs", [dict(dayfirst=True), dict(day_first=True)]) def test_parse_dates_custom_euro_format(all_parsers, kwargs): parser = all_parsers @@ -802,7 +803,7 @@ def test_parse_dates_custom_euro_format(all_parsers, kwargs): tm.assert_frame_equal(df, expected) else: msg = "got an unexpected keyword argument 'day_first'" - with pytest.raises(TypeError, match=msg), pytest.warns(FutureWarning): + with pytest.raises(TypeError, match=msg): parser.read_csv( StringIO(data), names=["time", "Q", "NTU"], @@ -1323,17 +1324,17 @@ def test_datetime_fractional_seconds(all_parsers): tm.assert_frame_equal(result, expected) +@pytest.mark.filterwarnings("ignore::FutureWarning") def test_generic(all_parsers): parser = all_parsers data = "year,month,day,a\n2001,01,10,10.\n2001,02,1,11." - with pytest.warns(FutureWarning): - result = parser.read_csv( - StringIO(data), - header=0, - parse_dates={"ym": [0, 1]}, - date_parser=lambda y, m: date(year=int(y), month=int(m), day=1), - ) + result = parser.read_csv( + StringIO(data), + header=0, + parse_dates={"ym": [0, 1]}, + date_parser=lambda y, m: date(year=int(y), month=int(m), day=1), + ) expected = DataFrame( [[date(2001, 1, 1), 10, 10.0], [date(2001, 2, 1), 1, 11.0]], columns=["ym", "day", "a"], From a4a3203adfaeac63d5076783747af3e716a89766 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Thu, 20 Aug 2020 23:01:00 +0200 Subject: [PATCH 12/19] Assert warnings in test_parse_dates.py instead of filtering warnings --- pandas/tests/io/parser/test_parse_dates.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index d5eae829f67f0..6b059d01ada6f 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -772,7 +772,6 @@ def test_multi_index_parse_dates(all_parsers, index_col): tm.assert_frame_equal(result, expected) -@pytest.mark.filterwarnings("ignore::FutureWarning") @pytest.mark.parametrize("kwargs", [dict(dayfirst=True), dict(day_first=True)]) def test_parse_dates_custom_euro_format(all_parsers, kwargs): parser = all_parsers @@ -803,7 +802,9 @@ def test_parse_dates_custom_euro_format(all_parsers, kwargs): tm.assert_frame_equal(df, expected) else: msg = "got an unexpected keyword argument 'day_first'" - with pytest.raises(TypeError, match=msg): + with pytest.raises(TypeError, match=msg), tm.assert_produces_warning( + FutureWarning + ): parser.read_csv( StringIO(data), names=["time", "Q", "NTU"], @@ -1324,17 +1325,17 @@ def test_datetime_fractional_seconds(all_parsers): tm.assert_frame_equal(result, expected) -@pytest.mark.filterwarnings("ignore::FutureWarning") def test_generic(all_parsers): parser = all_parsers data = "year,month,day,a\n2001,01,10,10.\n2001,02,1,11." - result = parser.read_csv( - StringIO(data), - header=0, - parse_dates={"ym": [0, 1]}, - date_parser=lambda y, m: date(year=int(y), month=int(m), day=1), - ) + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + result = parser.read_csv( + StringIO(data), + header=0, + parse_dates={"ym": [0, 1]}, + date_parser=lambda y, m: date(year=int(y), month=int(m), day=1), + ) expected = DataFrame( [[date(2001, 1, 1), 10, 10.0], [date(2001, 2, 1), 1, 11.0]], columns=["ym", "day", "a"], From 8d970ca7bfd405fc450c6e9bb650259ac245f489 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Tue, 25 Aug 2020 21:08:43 +0200 Subject: [PATCH 13/19] Update deprecated version and remove double doc string text --- pandas/io/date_converters.py | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index 55777f77e4296..0173e0b8e5264 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -10,10 +10,7 @@ def parse_date_time(date_col, time_col): """ Parse columns with dates and times into a single datetime column. - .. deprecated:: 1.1.0 - Use pd.to_datetime(date_col + " " + time_col) instead to get a Pandas Series. - Use pd.to_datetime(date_col + " " + time_col).to_pydatetime() instead to get - a Numpy array. + .. deprecated:: 1.2 """ warnings.warn( """ @@ -30,11 +27,7 @@ def parse_date_fields(year_col, month_col, day_col): """ Parse columns with years, months and days into a single date column. - .. deprecated:: 1.1.0 - Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) - instead to get a Pandas Series. - Use ser = pd.to_datetime({"year": year_col, "month": month_col, "day": day_col}) - and np.array([s.to_pydatetime() for s in ser]) instead to get a Numpy array. + .. deprecated:: 1.2 """ warnings.warn( """ @@ -54,13 +47,7 @@ def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_ """ Parse columns with datetime information into a single datetime column. - .. deprecated:: 1.1.0 - Use pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, - "hour": hour_col, "minute": minute_col, second": second_col}) instead to get - a Pandas Series. - Use ser = pd.to_datetime({"year": year_col, "month": month_col, "day": day_col, - "hour": hour_col, "minute": minute_col, second": second_col}) and - np.array([s.to_pydatetime() for s in ser]) instead to get a Numpy array. + .. deprecated:: 1.2 """ warnings.warn( @@ -93,8 +80,7 @@ def generic_parser(parse_func, *cols): """ Use dateparser to parse columns with data information into a single datetime column. - .. deprecated:: 1.1.0 - Use pd.to_datetime instead. + .. deprecated:: 1.2 """ warnings.warn( From 2033dc361687aca5be97bb9dcf06042fce4abf7b Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Tue, 25 Aug 2020 21:26:56 +0200 Subject: [PATCH 14/19] Revert to the old implementation of the date_converters function and just deprecate --- pandas/core/tools/datetimes.py | 20 +----------------- pandas/io/date_converters.py | 37 ++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/pandas/core/tools/datetimes.py b/pandas/core/tools/datetimes.py index 1eb8ee4434d39..0adab143f6052 100644 --- a/pandas/core/tools/datetimes.py +++ b/pandas/core/tools/datetimes.py @@ -6,7 +6,6 @@ TYPE_CHECKING, Callable, List, - MutableMapping, Optional, Tuple, TypeVar, @@ -60,7 +59,7 @@ # --------------------------------------------------------------------- # types used in annotations -ArrayConvertible = Union[List, Tuple, ArrayLike, "Series", MutableMapping] +ArrayConvertible = Union[List, Tuple, ArrayLike, "Series"] Scalar = Union[int, float, str] DatetimeScalar = TypeVar("DatetimeScalar", Scalar, datetime) DatetimeScalarOrArrayConvertible = Union[DatetimeScalar, ArrayConvertible] @@ -585,23 +584,6 @@ def to_datetime( ... -@overload -def to_datetime( - arg: MutableMapping, - errors: str = ..., - dayfirst: bool = ..., - yearfirst: bool = ..., - utc: Optional[bool] = ..., - format: Optional[str] = ..., - exact: bool = ..., - unit: Optional[str] = ..., - infer_datetime_format: bool = ..., - origin=..., - cache: bool = ..., -) -> "Series": - ... - - @overload def to_datetime( arg: Union[List, Tuple], diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index 0173e0b8e5264..f2cd5834ac90d 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -3,7 +3,7 @@ import numpy as np -from pandas import to_datetime +from pandas._libs.tslibs import parsing def parse_date_time(date_col, time_col): @@ -20,7 +20,9 @@ def parse_date_time(date_col, time_col): FutureWarning, stacklevel=2, ) - return to_datetime(date_col + " " + time_col).to_pydatetime() + date_col = _maybe_cast(date_col) + time_col = _maybe_cast(time_col) + return parsing.try_parse_date_and_time(date_col, time_col) def parse_date_fields(year_col, month_col, day_col): @@ -39,8 +41,10 @@ def parse_date_fields(year_col, month_col, day_col): stacklevel=2, ) - ser = to_datetime({"year": year_col, "month": month_col, "day": day_col}) - return np.array([s.to_pydatetime() for s in ser]) + year_col = _maybe_cast(year_col) + month_col = _maybe_cast(month_col) + day_col = _maybe_cast(day_col) + return parsing.try_parse_year_month_day(year_col, month_col, day_col) def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_col): @@ -62,19 +66,16 @@ def parse_all_fields(year_col, month_col, day_col, hour_col, minute_col, second_ stacklevel=2, ) - ser = to_datetime( - { - "year": year_col, - "month": month_col, - "day": day_col, - "hour": hour_col, - "minute": minute_col, - "second": second_col, - } + year_col = _maybe_cast(year_col) + month_col = _maybe_cast(month_col) + day_col = _maybe_cast(day_col) + hour_col = _maybe_cast(hour_col) + minute_col = _maybe_cast(minute_col) + second_col = _maybe_cast(second_col) + return parsing.try_parse_datetime_components( + year_col, month_col, day_col, hour_col, minute_col, second_col ) - return np.array([s.to_pydatetime() for s in ser]) - def generic_parser(parse_func, *cols): """ @@ -101,6 +102,12 @@ def generic_parser(parse_func, *cols): return results +def _maybe_cast(arr): + if not arr.dtype.type == np.object_: + arr = np.array(arr, dtype=object) + return arr + + def _check_columns(cols): if not len(cols): raise AssertionError("There must be at least 1 column") From 8f90441a086f61bf72a9750bca3039ba7693c245 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Wed, 26 Aug 2020 20:57:11 +0200 Subject: [PATCH 15/19] Remove superfluous noqa statement --- pandas/io/date_converters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/date_converters.py b/pandas/io/date_converters.py index f2cd5834ac90d..f079a25f69fec 100644 --- a/pandas/io/date_converters.py +++ b/pandas/io/date_converters.py @@ -87,7 +87,7 @@ def generic_parser(parse_func, *cols): warnings.warn( """ Use pd.to_datetime instead. -""", # noqa: E501 +""", FutureWarning, stacklevel=2, ) From 2a2a271be5ae708fc5d921cb7c86eb30fbd23418 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Wed, 26 Aug 2020 21:27:09 +0200 Subject: [PATCH 16/19] Only assert warnings for lines that produce a warning --- pandas/tests/io/test_date_converters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/io/test_date_converters.py b/pandas/tests/io/test_date_converters.py index 4fb53decfd887..a9fa27e091714 100644 --- a/pandas/tests/io/test_date_converters.py +++ b/pandas/tests/io/test_date_converters.py @@ -14,7 +14,7 @@ def test_parse_date_time(): expected = np.array([datetime(2007, 1, 3, 5, 7, 9), datetime(2008, 2, 4, 6, 8, 0)]) with tm.assert_produces_warning(FutureWarning): result = conv.parse_date_time(dates, times) - tm.assert_numpy_array_equal(result, expected) + tm.assert_numpy_array_equal(result, expected) def test_parse_date_fields(): @@ -25,7 +25,7 @@ def test_parse_date_fields(): with tm.assert_produces_warning(FutureWarning): result = conv.parse_date_fields(years, months, days) - tm.assert_numpy_array_equal(result, expected) + tm.assert_numpy_array_equal(result, expected) def test_parse_all_fields(): @@ -40,4 +40,4 @@ def test_parse_all_fields(): with tm.assert_produces_warning(FutureWarning): result = conv.parse_all_fields(years, months, days, hours, minutes, seconds) - tm.assert_numpy_array_equal(result, expected) + tm.assert_numpy_array_equal(result, expected) From 427bbf0ee666a34dcef44f9a02cf17707501cf85 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 29 Aug 2020 15:37:44 +0200 Subject: [PATCH 17/19] Add pytest parametrize to test old and new dateparser function --- pandas/tests/io/parser/test_parse_dates.py | 105 +++++++++++++++------ 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/pandas/tests/io/parser/test_parse_dates.py b/pandas/tests/io/parser/test_parse_dates.py index 6b059d01ada6f..c349f6b776a6f 100644 --- a/pandas/tests/io/parser/test_parse_dates.py +++ b/pandas/tests/io/parser/test_parse_dates.py @@ -23,6 +23,8 @@ import pandas._testing as tm from pandas.core.indexes.datetimes import date_range +import pandas.io.date_converters as conv + # constant _DEFAULT_DATETIME = datetime(1, 1, 1) @@ -368,7 +370,11 @@ def test_date_col_as_index_col(all_parsers): tm.assert_frame_equal(result, expected) -def test_multiple_date_cols_int_cast(all_parsers): +@pytest.mark.parametrize( + "date_parser, warning", + ([conv.parse_date_time, FutureWarning], [pd.to_datetime, None]), +) +def test_multiple_date_cols_int_cast(all_parsers, date_parser, warning): data = ( "KORD,19990127, 19:00:00, 18:56:00, 0.8100\n" "KORD,19990127, 20:00:00, 19:56:00, 0.0100\n" @@ -380,9 +386,15 @@ def test_multiple_date_cols_int_cast(all_parsers): parse_dates = {"actual": [1, 2], "nominal": [1, 3]} parser = all_parsers - result = parser.read_csv( - StringIO(data), header=None, parse_dates=parse_dates, prefix="X", - ) + with tm.assert_produces_warning(warning, check_stacklevel=False): + result = parser.read_csv( + StringIO(data), + header=None, + date_parser=date_parser, + parse_dates=parse_dates, + prefix="X", + ) + expected = DataFrame( [ [datetime(1999, 1, 27, 19, 0), datetime(1999, 1, 27, 18, 56), "KORD", 0.81], @@ -1162,7 +1174,11 @@ def test_parse_dates_no_convert_thousands(all_parsers, data, kwargs, expected): tm.assert_frame_equal(result, expected) -def test_parse_date_time_multi_level_column_name(all_parsers): +@pytest.mark.parametrize( + "date_parser, warning", + ([conv.parse_date_time, FutureWarning], [pd.to_datetime, None]), +) +def test_parse_date_time_multi_level_column_name(all_parsers, date_parser, warning): data = """\ D,T,A,B date, time,a,b @@ -1170,9 +1186,13 @@ def test_parse_date_time_multi_level_column_name(all_parsers): 2001-01-06, 00:00:00, 1.0, 11. """ parser = all_parsers - result = parser.read_csv( - StringIO(data), header=[0, 1], parse_dates={"date_time": [0, 1]}, - ) + with tm.assert_produces_warning(warning, check_stacklevel=False): + result = parser.read_csv( + StringIO(data), + header=[0, 1], + parse_dates={"date_time": [0, 1]}, + date_parser=date_parser, + ) expected_data = [ [datetime(2001, 1, 5, 9, 0, 0), 0.0, 10.0], @@ -1182,6 +1202,10 @@ def test_parse_date_time_multi_level_column_name(all_parsers): tm.assert_frame_equal(result, expected) +@pytest.mark.parametrize( + "date_parser, warning", + ([conv.parse_date_time, FutureWarning], [pd.to_datetime, None]), +) @pytest.mark.parametrize( "data,kwargs,expected", [ @@ -1254,9 +1278,10 @@ def test_parse_date_time_multi_level_column_name(all_parsers): ), ], ) -def test_parse_date_time(all_parsers, data, kwargs, expected): +def test_parse_date_time(all_parsers, data, kwargs, expected, date_parser, warning): parser = all_parsers - result = parser.read_csv(StringIO(data), **kwargs) + with tm.assert_produces_warning(warning, check_stacklevel=False): + result = parser.read_csv(StringIO(data), date_parser=date_parser, **kwargs) # Python can sometimes be flaky about how # the aggregated columns are entered, so @@ -1265,10 +1290,20 @@ def test_parse_date_time(all_parsers, data, kwargs, expected): tm.assert_frame_equal(result, expected) -def test_parse_date_fields(all_parsers): +@pytest.mark.parametrize( + "date_parser, warning", + ([conv.parse_date_fields, FutureWarning], [pd.to_datetime, None]), +) +def test_parse_date_fields(all_parsers, date_parser, warning): parser = all_parsers data = "year,month,day,a\n2001,01,10,10.\n2001,02,1,11." - result = parser.read_csv(StringIO(data), header=0, parse_dates={"ymd": [0, 1, 2]},) + with tm.assert_produces_warning(warning, check_stacklevel=False): + result = parser.read_csv( + StringIO(data), + header=0, + parse_dates={"ymd": [0, 1, 2]}, + date_parser=date_parser, + ) expected = DataFrame( [[datetime(2001, 1, 10), 10.0], [datetime(2001, 2, 1), 11.0]], @@ -1277,20 +1312,27 @@ def test_parse_date_fields(all_parsers): tm.assert_frame_equal(result, expected) -def test_parse_date_all_fields(all_parsers): - +@pytest.mark.parametrize( + "date_parser, warning", + ( + [conv.parse_all_fields, FutureWarning], + [lambda x: pd.to_datetime(x, format="%Y %m %d %H %M %S"), None], + ), +) +def test_parse_date_all_fields(all_parsers, date_parser, warning): parser = all_parsers data = """\ year,month,day,hour,minute,second,a,b 2001,01,05,10,00,0,0.0,10. 2001,01,5,10,0,00,1.,11. """ - result = parser.read_csv( - StringIO(data), - header=0, - date_parser=lambda x: pd.to_datetime(x, format="%Y %m %d %H %M %S"), - parse_dates={"ymdHMS": [0, 1, 2, 3, 4, 5]}, - ) + with tm.assert_produces_warning(warning, check_stacklevel=False): + result = parser.read_csv( + StringIO(data), + header=0, + date_parser=date_parser, + parse_dates={"ymdHMS": [0, 1, 2, 3, 4, 5]}, + ) expected = DataFrame( [ [datetime(2001, 1, 5, 10, 0, 0), 0.0, 10.0], @@ -1301,20 +1343,27 @@ def test_parse_date_all_fields(all_parsers): tm.assert_frame_equal(result, expected) -def test_datetime_fractional_seconds(all_parsers): +@pytest.mark.parametrize( + "date_parser, warning", + ( + [conv.parse_all_fields, FutureWarning], + [lambda x: pd.to_datetime(x, format="%Y %m %d %H %M %S.%f"), None], + ), +) +def test_datetime_fractional_seconds(all_parsers, date_parser, warning): parser = all_parsers data = """\ year,month,day,hour,minute,second,a,b 2001,01,05,10,00,0.123456,0.0,10. 2001,01,5,10,0,0.500000,1.,11. """ - result = parser.read_csv( - StringIO(data), - header=0, - # date_parser=conv.parse_all_fields, - date_parser=lambda x: pd.to_datetime(x, format="%Y %m %d %H %M %S.%f"), - parse_dates={"ymdHMS": [0, 1, 2, 3, 4, 5]}, - ) + with tm.assert_produces_warning(warning, check_stacklevel=False): + result = parser.read_csv( + StringIO(data), + header=0, + date_parser=date_parser, + parse_dates={"ymdHMS": [0, 1, 2, 3, 4, 5]}, + ) expected = DataFrame( [ [datetime(2001, 1, 5, 10, 0, 0, microsecond=123456), 0.0, 10.0], From 2d80bdc4422dda927f15df917ff89c4551d032cc Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sun, 6 Sep 2020 22:42:11 +0200 Subject: [PATCH 18/19] Add whatsnew entry --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index d7d2e3cf876ca..6e10ec0cbf528 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -195,7 +195,7 @@ Deprecations ~~~~~~~~~~~~ - Deprecated parameter ``inplace`` in :meth:`MultiIndex.set_codes` and :meth:`MultiIndex.set_levels` (:issue:`35626`) - Deprecated parameter ``dtype`` in :~meth:`Index.copy` on method all index classes. Use the :meth:`Index.astype` method instead for changing dtype(:issue:`35853`) -- +- Date parser functions :func:`parse_date_time`, :func:`parse_date_fields`, :func:`parse_all_fields` and :func:`generic_parser` from ``pandas.io.date_converters`` are deprecated and will be removed in a future version; use pandas.to_datetime() instead (GH35741) .. --------------------------------------------------------------------------- From 1458bc77fb7d873d3e76023123e2e9c003cdf242 Mon Sep 17 00:00:00 2001 From: Avinash Pancham Date: Sat, 12 Sep 2020 15:47:28 +0200 Subject: [PATCH 19/19] Update references in whatsnew message --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 6e10ec0cbf528..553954b466071 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -195,7 +195,7 @@ Deprecations ~~~~~~~~~~~~ - Deprecated parameter ``inplace`` in :meth:`MultiIndex.set_codes` and :meth:`MultiIndex.set_levels` (:issue:`35626`) - Deprecated parameter ``dtype`` in :~meth:`Index.copy` on method all index classes. Use the :meth:`Index.astype` method instead for changing dtype(:issue:`35853`) -- Date parser functions :func:`parse_date_time`, :func:`parse_date_fields`, :func:`parse_all_fields` and :func:`generic_parser` from ``pandas.io.date_converters`` are deprecated and will be removed in a future version; use pandas.to_datetime() instead (GH35741) +- Date parser functions :func:`~pandas.io.date_converters.parse_date_time`, :func:`~pandas.io.date_converters.parse_date_fields`, :func:`~pandas.io.date_converters.parse_all_fields` and :func:`~pandas.io.date_converters.generic_parser` from ``pandas.io.date_converters`` are deprecated and will be removed in a future version; use :func:`to_datetime` instead (:issue:`35741`) .. ---------------------------------------------------------------------------