Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Fix date_format and datetime_format arguments to ExcelWriter being ignored #47315

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,8 @@ I/O
- Bug in :func:`read_sas` with RLE-compressed SAS7BDAT files that contain 0x00 control bytes (:issue:`47099`)
- Bug in :func:`read_parquet` with ``use_nullable_dtypes=True`` where ``float64`` dtype was returned instead of nullable ``Float64`` dtype (:issue:`45694`)
- Bug in :meth:`DataFrame.to_json` where ``PeriodDtype`` would not make the serialization roundtrip when read back with :meth:`read_json` (:issue:`44720`)
- Bug in :class:`ExcelWriter` not respecting ``date_format`` and ``datetime_format`` (:issue:`44284`)
-

Period
^^^^^^
Expand Down
4 changes: 3 additions & 1 deletion pandas/io/excel/_odswriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(
path: FilePath | WriteExcelBuffer | ExcelWriter,
engine: str | None = None,
date_format: str | None = None,
datetime_format=None,
datetime_format: str | None = None,
mode: str = "w",
storage_options: StorageOptions = None,
if_sheet_exists: str | None = None,
Expand All @@ -47,6 +47,8 @@ def __init__(

super().__init__(
path,
date_format=date_format,
datetime_format=datetime_format,
mode=mode,
storage_options=storage_options,
if_sheet_exists=if_sheet_exists,
Expand Down
2 changes: 2 additions & 0 deletions pandas/io/excel/_openpyxl.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ def __init__(

super().__init__(
path,
date_format=date_format,
datetime_format=datetime_format,
mode=mode,
storage_options=storage_options,
if_sheet_exists=if_sheet_exists,
Expand Down
2 changes: 2 additions & 0 deletions pandas/io/excel/_xlwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def __init__(

super().__init__(
path,
date_format=date_format,
datetime_format=datetime_format,
mode=mode,
storage_options=storage_options,
if_sheet_exists=if_sheet_exists,
Expand Down
37 changes: 37 additions & 0 deletions pandas/tests/io/excel/test_openpyxl.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import contextlib
from datetime import (
date,
datetime,
)
from pathlib import Path
import re

Expand All @@ -10,6 +14,7 @@
import pandas._testing as tm

from pandas.io.excel import (
ExcelFile,
ExcelWriter,
_OpenpyxlWriter,
)
Expand Down Expand Up @@ -410,3 +415,35 @@ def test_read_multiindex_header_no_index_names(datapath, ext):
index=pd.MultiIndex.from_tuples([("A", "AA", "AAA"), ("A", "BB", "BBB")]),
)
tm.assert_frame_equal(result, expected)


def test_write_date_datetime_format(ext):
# see gh-44284
df = DataFrame(
[
[date(2014, 1, 31), datetime(1998, 5, 26, 23, 33, 4)],
[date(1999, 9, 24), datetime(2014, 2, 28, 13, 5, 13)],
],
index=["X", "Y"],
columns=["DATE", "DATETIME"],
)

with tm.ensure_clean(ext) as f:
with ExcelWriter(
f,
engine="xlsxwriter",
date_format="DD.MM.YYYY",
datetime_format="DD.MM.YYYY HH-MM-SS",
) as writer:
df.to_excel(writer, "test1")

with ExcelFile(f) as reader:
ws = reader.book["test1"]

date_cells = (ws["B2"], ws["B3"])
assert all(cell.number_format == "DD.MM.YYYY" for cell in date_cells)

datetime_cells = (ws["C2"], ws["C3"])
assert all(
cell.number_format == "DD.MM.YYYY HH-MM-SS" for cell in datetime_cells
)
41 changes: 40 additions & 1 deletion pandas/tests/io/excel/test_xlsxwriter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import contextlib
from datetime import (
date,
datetime,
)
import re
import warnings

Expand All @@ -7,7 +11,10 @@
from pandas import DataFrame
import pandas._testing as tm

from pandas.io.excel import ExcelWriter
from pandas.io.excel import (
ExcelFile,
ExcelWriter,
)

xlsxwriter = pytest.importorskip("xlsxwriter")

Expand Down Expand Up @@ -92,3 +99,35 @@ def test_book_and_sheets_consistent(ext):
assert writer.sheets == {}
sheet = writer.book.add_worksheet("test_name")
assert writer.sheets == {"test_name": sheet}


def test_write_date_datetime_format(ext):
# see gh-44284
df = DataFrame(
[
[date(2014, 1, 31), datetime(1998, 5, 26, 23, 33, 4)],
[date(1999, 9, 24), datetime(2014, 2, 28, 13, 5, 13)],
],
index=["X", "Y"],
columns=["DATE", "DATETIME"],
)

with tm.ensure_clean(ext) as f:
with ExcelWriter(
f,
engine="xlsxwriter",
date_format="DD.MM.YYYY",
datetime_format="DD.MM.YYYY HH-MM-SS",
) as writer:
df.to_excel(writer, "test1")

with ExcelFile(f) as reader:
ws = reader.book["test1"]

date_cells = (ws["B2"], ws["B3"])
assert all(cell.number_format == "DD.MM.YYYY" for cell in date_cells)

datetime_cells = (ws["C2"], ws["C3"])
assert all(
cell.number_format == "DD.MM.YYYY HH-MM-SS" for cell in datetime_cells
)
47 changes: 47 additions & 0 deletions pandas/tests/io/excel/test_xlwt.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from datetime import (
date,
datetime,
)
import re

import numpy as np
Expand Down Expand Up @@ -144,3 +148,46 @@ def test_deprecated_attr(ext, attr):
msg = f"{attr} is not part of the public API"
with tm.assert_produces_warning(FutureWarning, match=msg):
getattr(writer, attr)


def test_write_date_datetime_format(ext):
# see gh-44284
xlrd = pytest.importorskip("xlrd")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed. It's already called near the top of the file


df = DataFrame(
[
[date(2014, 1, 31), datetime(1998, 5, 26, 23, 33, 4)],
[date(1999, 9, 24), datetime(2014, 2, 28, 13, 5, 13)],
],
index=["X", "Y"],
columns=["DATE", "DATETIME"],
)

with tm.ensure_clean(ext) as f:
with ExcelWriter(
f,
engine="xlwt",
date_format="DD.MM.YYYY",
datetime_format="DD.MM.YYYY HH-MM-SS",
) as writer:
df.to_excel(writer, "test1")

# formatting_info defaults to False
# so have to use xlrd.open_workbook() directly
with xlrd.open_workbook(f, formatting_info=True) as book:
sh = book["test1"]
xf_list = book.xf_list
format_map = book.format_map

date_cells = (sh[1, 1], sh[2, 1])
assert all(
format_map[xf_list[cell.xf_index].format_key].format_str == "DD.MM.YYYY"
for cell in date_cells
)

datetime_cells = (sh[1, 2], sh[2, 2])
assert all(
format_map[xf_list[cell.xf_index].format_key].format_str
== "DD.MM.YYYY HH-MM-SS"
for cell in datetime_cells
)