diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 58ac2b4cba3b7..408b7d6235f3d 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -405,7 +405,7 @@ I/O - Bug in :meth:`read_csv` was causing a segfault when there were blank lines between the header and data rows (:issue:`28071`) - Bug in :meth:`read_csv` was raising a misleading exception on a permissions issue (:issue:`23784`) - Bug in :meth:`read_csv` was raising an ``IndexError`` when header=None and 2 extra data columns - +- Bug in :meth:`DataFrame.to_sql` where an ``AttributeError`` was raised when saving an out of bounds date (:issue:`26761`) Plotting ^^^^^^^^ diff --git a/pandas/io/sql.py b/pandas/io/sql.py index 560e7e4781cbb..ff647040ebbfb 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -978,7 +978,8 @@ def _sqlalchemy_type(self, col): return TIMESTAMP(timezone=True) except AttributeError: # The column is actually a DatetimeIndex - if col.tz is not None: + # GH 26761 or an Index with date-like data e.g. 9999-01-01 + if getattr(col, "tz", None) is not None: return TIMESTAMP(timezone=True) return DateTime if col_type == "timedelta64": diff --git a/pandas/tests/io/test_sql.py b/pandas/tests/io/test_sql.py index bf0ed4fe25346..2f2ae8cd9d32b 100644 --- a/pandas/tests/io/test_sql.py +++ b/pandas/tests/io/test_sql.py @@ -1480,6 +1480,14 @@ def test_datetime_with_timezone_roundtrip(self): result["A"] = to_datetime(result["A"]) tm.assert_frame_equal(result, expected) + def test_out_of_bounds_datetime(self): + # GH 26761 + data = pd.DataFrame({"date": datetime(9999, 1, 1)}, index=[0]) + data.to_sql("test_datetime_obb", self.conn, index=False) + result = sql.read_sql_table("test_datetime_obb", self.conn) + expected = pd.DataFrame([pd.NaT], columns=["date"]) + tm.assert_frame_equal(result, expected) + def test_naive_datetimeindex_roundtrip(self): # GH 23510 # Ensure that a naive DatetimeIndex isn't converted to UTC