Skip to content

Commit 7658a6a

Browse files
authored
Bug: to_csv coercing datetime columns to same format (#44964)
1 parent 0e58307 commit 7658a6a

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ I/O
766766
- Bug in :func:`read_csv` converting columns to numeric after date parsing failed (:issue:`11019`)
767767
- Bug in :func:`read_csv` not replacing ``NaN`` values with ``np.nan`` before attempting date conversion (:issue:`26203`)
768768
- Bug in :func:`read_csv` raising ``AttributeError`` when attempting to read a .csv file and infer index column dtype from an nullable integer type (:issue:`44079`)
769+
- Bug in :func:`to_csv` always coercing datetime columns with different formats to the same format (:issue:`21734`)
769770
- :meth:`DataFrame.to_csv` and :meth:`Series.to_csv` with ``compression`` set to ``'zip'`` no longer create a zip file containing a file ending with ".zip". Instead, they try to infer the inner file name more smartly. (:issue:`39465`)
770771
- Bug in :func:`read_csv` where reading a mixed column of booleans and missing values to a float type results in the missing values becoming 1.0 rather than NaN (:issue:`42808`, :issue:`34120`)
771772
- Bug in :func:`read_csv` when passing simultaneously a parser in ``date_parser`` and ``parse_dates=False``, the parsing was still called (:issue:`44366`)

pandas/core/internals/blocks.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -2100,9 +2100,17 @@ def to_native_types(
21002100
values = ensure_wrapped_if_datetimelike(values)
21012101

21022102
if isinstance(values, (DatetimeArray, TimedeltaArray)):
2103-
result = values._format_native_types(na_rep=na_rep, **kwargs)
2104-
result = result.astype(object, copy=False)
2105-
return result
2103+
if values.ndim == 1:
2104+
result = values._format_native_types(na_rep=na_rep, **kwargs)
2105+
result = result.astype(object, copy=False)
2106+
return result
2107+
2108+
# GH#21734 Process every column separately, they might have different formats
2109+
results_converted = []
2110+
for i in range(len(values)):
2111+
result = values[i, :]._format_native_types(na_rep=na_rep, **kwargs)
2112+
results_converted.append(result.astype(object, copy=False))
2113+
return np.vstack(results_converted)
21062114

21072115
elif isinstance(values, ExtensionArray):
21082116
mask = isna(values)

pandas/tests/io/formats/test_to_csv.py

+16
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,22 @@ def test_to_csv_date_format(self):
282282
df_sec_grouped = df_sec.groupby([pd.Grouper(key="A", freq="1h"), "B"])
283283
assert df_sec_grouped.mean().to_csv(date_format="%Y-%m-%d") == expected_ymd_sec
284284

285+
def test_to_csv_different_datetime_formats(self):
286+
# GH#21734
287+
df = DataFrame(
288+
{
289+
"date": pd.to_datetime("1970-01-01"),
290+
"datetime": pd.date_range("1970-01-01", periods=2, freq="H"),
291+
}
292+
)
293+
expected_rows = [
294+
"date,datetime",
295+
"1970-01-01,1970-01-01 00:00:00",
296+
"1970-01-01,1970-01-01 01:00:00",
297+
]
298+
expected = tm.convert_rows_list_to_csv_str(expected_rows)
299+
assert df.to_csv(index=False) == expected
300+
285301
def test_to_csv_date_format_in_categorical(self):
286302
# GH#40754
287303
ser = pd.Series(pd.to_datetime(["2021-03-27", pd.NaT], format="%Y-%m-%d"))

0 commit comments

Comments
 (0)