Skip to content

Commit

Permalink
FIX: handle NaT values in dt-accessor (#8084)
Browse files Browse the repository at this point in the history
* FIX: handle NaT values in dt-accessor
* FIX: only use isnat-check for datetimes not cftime
* check for <NA> and apply needed dtype for isocalendar
* Keep current version without NaT
* add whats-new.rst entry
  • Loading branch information
kmuehlbauer authored Sep 14, 2023
1 parent 218ea21 commit 0c4f165
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
4 changes: 4 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ Bug fixes
- Fix bug where :py:class:`DataArray` instances on the right-hand side
of :py:meth:`DataArray.__setitem__` lose dimension names.
(:issue:`7030`, :pull:`8067`) By `Darsh Ranjan <https://github.com/dranjan>`_.
- Return ``float64`` in presence of ``NaT`` in :py:class:`~core.accessor_dt.DatetimeAccessor` and
special case ``NaT`` handling in :py:meth:`~core.accessor_dt.DatetimeAccessor.isocalendar()`
(:issue:`7928`, :pull:`8084`).
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_.

Documentation
~~~~~~~~~~~~~
Expand Down
25 changes: 22 additions & 3 deletions xarray/core/accessor_dt.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,25 @@ def _access_through_series(values, name):
months = values_as_series.dt.month.values
field_values = _season_from_months(months)
elif name == "isocalendar":
# special NaT-handling can be removed when
# https://github.com/pandas-dev/pandas/issues/54657 is resolved
field_values = values_as_series.dt.isocalendar()
# test for <NA> and apply needed dtype
hasna = any(field_values.year.isnull())
if hasna:
field_values = np.dstack(
[
getattr(field_values, name).astype(np.float64, copy=False).values
for name in ["year", "week", "day"]
]
)
else:
field_values = np.array(field_values, dtype=np.int64)
# isocalendar returns iso- year, week, and weekday -> reshape
field_values = np.array(values_as_series.dt.isocalendar(), dtype=np.int64)
return field_values.T.reshape(3, *values.shape)
else:
field_values = getattr(values_as_series.dt, name).values

return field_values.reshape(values.shape)


Expand Down Expand Up @@ -110,7 +124,7 @@ def _get_date_field(values, name, dtype):
from dask.array import map_blocks

new_axis = chunks = None
# isocalendar adds adds an axis
# isocalendar adds an axis
if name == "isocalendar":
chunks = (3,) + values.chunksize
new_axis = 0
Expand All @@ -119,7 +133,12 @@ def _get_date_field(values, name, dtype):
access_method, values, name, dtype=dtype, new_axis=new_axis, chunks=chunks
)
else:
return access_method(values, name).astype(dtype, copy=False)
out = access_method(values, name)
# cast only for integer types to keep float64 in presence of NaT
# see https://github.com/pydata/xarray/issues/7928
if np.issubdtype(out.dtype, np.integer):
out = out.astype(dtype, copy=False)
return out


def _round_through_series_or_index(values, name, freq):
Expand Down

0 comments on commit 0c4f165

Please sign in to comment.