From 275d478bb9bcece8b44bb52b9be6109555b9110f Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sat, 29 Jun 2019 11:44:33 -0500 Subject: [PATCH 1/4] ERR: Raise error in to_excel when saving datetimes with timezones --- doc/source/whatsnew/v0.25.0.rst | 1 + pandas/io/formats/excel.py | 4 ++++ pandas/tests/io/excel/test_writers.py | 15 +++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 008f6f0b8643e..bddf02e29110c 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -561,6 +561,7 @@ Other API changes - The ``.str``-accessor has been disabled for 1-level :class:`MultiIndex`, use :meth:`MultiIndex.to_flat_index` if necessary (:issue:`23679`) - Removed support of gtk package for clipboards (:issue:`26563`) - Using an unsupported version of Beautiful Soup 4 will now raise an ``ImportError`` instead of a ``ValueError`` (:issue:`27063`) +- :meth:`Series.to_excel` and :meth:`DataFrame.to_excel` will now raise a ``ValueError`` when saving timezone aware data. (:issue:`27008`, :issue:`7056`) .. _whatsnew_0250.deprecations: diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 5792f6e2a5a08..07de3db181a54 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -402,6 +402,10 @@ def _format_value(self, val): val = '-{inf}'.format(inf=self.inf_rep) elif self.float_format is not None: val = float(self.float_format % val) + if getattr(val, 'tzinfo', None) is not None: + raise ValueError('Excel does not support datetimes with timzones. ' + 'Please ensure that datetimes are timezone ' + 'unaware before writing to Excel.') return val def _format_header_mi(self): diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index a4fdcdf70a3ea..0c9214bce154b 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -1178,6 +1178,21 @@ def test_merged_cell_custom_objects(self, engine, merge_cells, ext): expected.index = expected.index.astype(np.float64) tm.assert_frame_equal(expected, result) + @pytest.mark.parametrize('dtype', [None, object]) + def test_raise_when_saving_timezones(self, engine, ext, dtype, + tz_aware_fixture): + # GH 27008, GH 7056 + tz = tz_aware_fixture + data = pd.Timestamp('2019', tz=tz) + df = DataFrame([data], dtype=dtype) + with pytest.raises(ValueError, match="Excel does not support"): + df.to_excel(self.path, engine=engine) + + data = data.to_pydatetime() + df = DataFrame([data], dtype=dtype) + with pytest.raises(ValueError, match="Excel does not support"): + df.to_excel(self.path, engine=engine) + class TestExcelWriterEngineTests: From bc598abc7491af4686fba3850ea8d9e559333048 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sat, 29 Jun 2019 11:59:52 -0500 Subject: [PATCH 2/4] Remove unnecessary setting of engine --- pandas/tests/io/excel/test_writers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 0c9214bce154b..8f20136f1ea4b 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -1186,12 +1186,12 @@ def test_raise_when_saving_timezones(self, engine, ext, dtype, data = pd.Timestamp('2019', tz=tz) df = DataFrame([data], dtype=dtype) with pytest.raises(ValueError, match="Excel does not support"): - df.to_excel(self.path, engine=engine) + df.to_excel(self.path) data = data.to_pydatetime() df = DataFrame([data], dtype=dtype) with pytest.raises(ValueError, match="Excel does not support"): - df.to_excel(self.path, engine=engine) + df.to_excel(self.path) class TestExcelWriterEngineTests: From a5d10551dcfb93214b8a05b9f66c9ca48533cfdd Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sat, 29 Jun 2019 12:06:56 -0500 Subject: [PATCH 3/4] Typo --- pandas/io/formats/excel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 07de3db181a54..ccdab2a2f39dc 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -403,7 +403,7 @@ def _format_value(self, val): elif self.float_format is not None: val = float(self.float_format % val) if getattr(val, 'tzinfo', None) is not None: - raise ValueError('Excel does not support datetimes with timzones. ' + raise ValueError('Excel does not support datetimes with timezones. ' 'Please ensure that datetimes are timezone ' 'unaware before writing to Excel.') return val From 823dcb26d1cd341dd220ef033a01c0f5abd2ac21 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sat, 29 Jun 2019 12:08:37 -0500 Subject: [PATCH 4/4] Flake8 --- pandas/io/formats/excel.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index ccdab2a2f39dc..66a00bf9ab054 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -403,9 +403,9 @@ def _format_value(self, val): elif self.float_format is not None: val = float(self.float_format % val) if getattr(val, 'tzinfo', None) is not None: - raise ValueError('Excel does not support datetimes with timezones. ' - 'Please ensure that datetimes are timezone ' - 'unaware before writing to Excel.') + raise ValueError('Excel does not support datetimes with ' + 'timezones. Please ensure that datetimes ' + 'are timezone unaware before writing to Excel.') return val def _format_header_mi(self):