Repository: dask/dask

Issue:
dask.dataframe.read_parquet infers pyarrow.decimal128 as datetimelike
**What happened**:

`dask.dataframe.read_parquet` infers `pyarrow.decimal128` as datetimelike.

**What you expected to happen**:

I expect `dask.dataframe.read_parquet` to infer `pyarrow.decimal128` as `object`.

**Minimal Complete Verifiable Example**:

```python
from decimal import Decimal
import random
import shutil

import dask.dataframe as dd
import numpy as np
import pandas as pd
import pyarrow as pa


FILE_NAME = "my_data.parquet"

schema = pa.schema([pa.field("col1", pa.decimal128(5, 2))])

random.seed(0)
data = [{"col1": Decimal(f"{random.randint(0, 346)}.00")} for i in range(23)]
ddf = dd.from_pandas(pd.DataFrame(data), npartitions=1)

try:
    shutil.rmtree(FILE_NAME)
except FileNotFoundError:
    pass

ddf.to_parquet(path=FILE_NAME, engine="pyarrow", schema=schema)
ddf2 = dd.read_parquet(path=FILE_NAME, engine="pyarrow")

assert np.dtype("O") == ddf.dtypes.to_dict()["col1"]
assert (
    np.dtype("<M8[ns]") == ddf2.dtypes.to_dict()["col1"]
)  # ddf2.col1 is `datetime64[ns]` instead of `object`.

assert np.dtype("O") == ddf2.dtypes.to_dict()["col1"], "col1 should be an object".    # AssertionError is raised.
```

**Environment**:

- Dask version: 2.30.0
- Pandas version: 1.0.3 and 1.1.5 
- Python version: 3.7.7
- Pyarrow version: 0.16.0, 0.17.1, 1.0.1, and 2.0.0
- Operating System: macOS Catalina and Amazon Linux
- Install method: poetry



Discussion:
I can reproduce on latest master, thanks for the detailed report! I found that when you call compute on the resultant dataframe you end up with dtype `object`:

```python
assert np.dtype("O") == ddf2.compute().dtypes.to_dict()["col1"]
```
So I imagine the issue must be with some assumption in the meta construction.  

Resolving patch:
diff --git a/dask/dataframe/io/utils.py b/dask/dataframe/io/utils.py
--- a/dask/dataframe/io/utils.py
+++ b/dask/dataframe/io/utils.py
@@ -19,7 +19,7 @@ def _get_pyarrow_dtypes(schema, categories):
                 "timezone", None
             )
             for c in pandas_metadata.get("columns", [])
-            if c["metadata"]
+            if c["pandas_type"] in ("datetime", "datetimetz") and c["metadata"]
         }
     else:
         pandas_metadata_dtypes = {}


Test patch:
diff --git a/dask/dataframe/io/tests/test_parquet.py b/dask/dataframe/io/tests/test_parquet.py
--- a/dask/dataframe/io/tests/test_parquet.py
+++ b/dask/dataframe/io/tests/test_parquet.py
@@ -3,6 +3,7 @@
 import os
 import sys
 import warnings
+from decimal import Decimal
 from distutils.version import LooseVersion
 
 import numpy as np
@@ -3310,3 +3311,24 @@ def test_dir_filter(tmpdir, engine):
     ddf.to_parquet(tmpdir, partition_on="year", engine=engine)
     dd.read_parquet(tmpdir, filters=[("year", "==", 2020)], engine=engine)
     assert all
+
+
+def test_roundtrip_decimal_dtype(tmpdir):
+    # https://github.com/dask/dask/issues/6948
+    check_pyarrow()
+    tmpdir = str(tmpdir)
+
+    data = [
+        {
+            "ts": pd.to_datetime("2021-01-01", utc="Europe/Berlin"),
+            "col1": Decimal("123.00"),
+        }
+        for i in range(23)
+    ]
+    ddf1 = dd.from_pandas(pd.DataFrame(data), npartitions=1)
+
+    ddf1.to_parquet(path=tmpdir, engine="pyarrow")
+    ddf2 = dd.read_parquet(tmpdir, engine="pyarrow")
+
+    assert ddf1["col1"].dtype == ddf2["col1"].dtype
+    assert_eq(ddf1, ddf2, check_divisions=False)