Repository: geopandas/geopandas

Issue:
BUG: AttributeError about datetimelike values when reading file with Fiona engine
- [x] I have checked that this issue has not already been reported.

- [x] I have confirmed this bug exists on the latest version of geopandas (on the date of issue, last version is 0.11.0).

- [ ] (optional) I have confirmed this bug exists on the main branch of geopandas.

---

**Note**: Please read [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) detailing how to provide the necessary information for us to reproduce your bug.

#### Code Sample, a copy-pastable example

```python
import geopandas as gpd

path_to_file = <path to the file attached>
gdf = gpd.read_file(path_to_file)
```

#### Problem description
The attached file contains date-like columns. With the last version of geopandas I'm not able to read it anymore, as it raises an AttributeError `AttributeError: Can only use .dt accessor with datetimelike values`.

It was not the case with previous version of geopandas. The date-like columns were identified as object columns but at least no error were raised.

If I switch the engine from Fiona to Pyogrio to read the file, there is no error raised and all columns are well detected as datetime columns.

#### Expected Output

Have all columns parsed with no error raised. Here the output I obtained with engine Pyogrio instead of Fiona:
```
>>> gdf.dtypes
cleabs                             object
nature                             object
nature_detaillee                   object
toponyme                           object
statut_du_toponyme                 object
fictif                               bool
etat_de_l_objet                    object
date_creation              datetime64[ns]
date_modification          datetime64[ns]
date_d_apparition          datetime64[ns]
date_de_confirmation       datetime64[ns]
sources                            object
identifiants_sources               object
precision_planimetrique           float64
geometry                         geometry
```
#### Output of ``geopandas.show_versions()``

<details> 
<pre>
SYSTEM INFO
-----------
python     : 3.8.10 (default, Mar 15 2022, 12:22:08)  [GCC 9.4.0]
executable : my_env/bin/python
machine    : Linux-5.13.0-51-generic-x86_64-with-glibc2.29

GEOS, GDAL, PROJ INFO
---------------------
GEOS       : None
GEOS lib   : None
GDAL       : 3.4.1
GDAL data dir: my_env/lib/python3.8/site-packages/fiona/gdal_data
PROJ       : 8.2.0
PROJ data dir: my_env/lib/python3.8/site-packages/pyproj/proj_dir/share/proj

PYTHON DEPENDENCIES
-------------------
geopandas  : 0.11.0
pandas     : 1.4.3
fiona      : 1.8.21
numpy      : 1.23.0
shapely    : 1.8.2
rtree      : None
pyproj     : 3.3.1
matplotlib : None
mapclassify: None
geopy      : None
psycopg2   : None
geoalchemy2: None
pyarrow    : None
pygeos     : None
</pre>

</details>

Attached file: [grosfi.ch/GzMKuv5CHgu](https://www.grosfichiers.com/GzMKuv5CHgu)


Discussion:
Cc @m-richards as you did the PR changing this. 
Thanks @paumillet (and @martinfleis for tagging me)

This is happening because the datetime data in the source file contains mixed timezone offsets and so doesn't fit into the pandas datetime model
```python
pd.to_datetime(["2014-08-26 10:01:23.040001+02:00"]).dtype # datetime64[ns, pytz.FixedOffset(120)]
pd.to_datetime(["2014-08-26 10:01:23.040001+02:00", "2019-03-07 17:31:43.118999+01:00"]).dtype # dtype('O')
```
I guess we can fall back to object dtypes in this case


Resolving patch:
diff --git a/geopandas/io/file.py b/geopandas/io/file.py
--- a/geopandas/io/file.py
+++ b/geopandas/io/file.py
@@ -341,9 +341,15 @@ def _read_file_fiona(
                     f_filt, crs=crs, columns=columns + ["geometry"]
                 )
             for k in datetime_fields:
-                # fiona only supports up to ms precision, any microseconds are
-                # floating point rounding error
-                df[k] = pd.to_datetime(df[k]).dt.round(freq="ms")
+                as_dt = pd.to_datetime(df[k])
+                # if to_datetime failed, try again for mixed timezone offsets
+                if as_dt.dtype == "object":
+                    # This can fail if there are invalid datetimes
+                    as_dt = pd.to_datetime(df[k], utc=True)
+                # if to_datetime succeeded, round datetimes as
+                # fiona only supports up to ms precision
+                if not (as_dt.dtype == "object"):
+                    df[k] = as_dt.dt.round(freq="ms")
             return df
 
 


Test patch:
diff --git a/geopandas/io/tests/test_file.py b/geopandas/io/tests/test_file.py
--- a/geopandas/io/tests/test_file.py
+++ b/geopandas/io/tests/test_file.py
@@ -10,6 +10,7 @@
 import pandas as pd
 
 import pytz
+from pandas.api.types import is_datetime64_any_dtype
 from pandas.testing import assert_series_equal
 from shapely.geometry import Point, Polygon, box
 
@@ -231,6 +232,28 @@ def test_to_file_datetime(tmpdir, driver, ext, time, engine):
         assert_series_equal(df["b"], df_read["b"])
 
 
+def test_read_file_mixed_datetimes(tmpdir):
+    tempfilename = os.path.join(str(tmpdir), "test_mixed_datetime.geojson")
+    df = GeoDataFrame(
+        {
+            "date": [
+                "2014-08-26 10:01:23.040001+02:00",
+                "2019-03-07 17:31:43.118999+01:00",
+            ],
+            "geometry": [Point(1, 1), Point(1, 1)],
+        }
+    )
+    df.to_file(tempfilename)
+    res = read_file(tempfilename)  # check mixed tz don't crash GH2478
+    assert is_datetime64_any_dtype(res["date"])
+    if FIONA_GE_1814:
+        # Convert mixed timezones to UTC equivalent
+        assert res["date"].dt.tz == pytz.utc
+    else:
+        # old fiona and pyogrio ignore timezones and read as datetimes successfully
+        assert is_datetime64_any_dtype(res["date"])
+
+
 @pytest.mark.parametrize("driver,ext", driver_ext_pairs)
 def test_to_file_with_point_z(tmpdir, ext, driver, engine):
     """Test that 3D geometries are retained in writes (GH #612)."""