Skip to content

Commit 38b0a40

Browse files
authoredJun 16, 2022
ENH: DTA/DTI __repr__ support non-nano (#47374)
* ENH: DTA/DTI __repr__ support non-nano * mypy fixup
1 parent c6e7d8d commit 38b0a40

File tree

6 files changed

+41
-12
lines changed

6 files changed

+41
-12
lines changed
 

‎pandas/_libs/tslib.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def format_array_from_datetime(
99
tz: tzinfo | None = ...,
1010
format: str | None = ...,
1111
na_rep: object = ...,
12+
reso: int = ..., # NPY_DATETIMEUNIT
1213
) -> npt.NDArray[np.object_]: ...
1314
def array_with_unit_to_datetime(
1415
values: np.ndarray,

‎pandas/_libs/tslib.pyx

+8-5
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ import pytz
2828

2929
from pandas._libs.tslibs.np_datetime cimport (
3030
NPY_DATETIMEUNIT,
31+
NPY_FR_ns,
3132
check_dts_bounds,
32-
dt64_to_dtstruct,
3333
dtstruct_to_dt64,
3434
get_datetime64_value,
3535
npy_datetimestruct,
36+
pandas_datetime_to_datetimestruct,
3637
pydate_to_dt64,
3738
pydatetime_to_dt64,
3839
string_to_dts,
@@ -107,7 +108,8 @@ def format_array_from_datetime(
107108
ndarray[int64_t] values,
108109
tzinfo tz=None,
109110
str format=None,
110-
object na_rep=None
111+
object na_rep=None,
112+
NPY_DATETIMEUNIT reso=NPY_FR_ns,
111113
) -> np.ndarray:
112114
"""
113115
return a np object array of the string formatted values
@@ -120,6 +122,7 @@ def format_array_from_datetime(
120122
a strftime capable string
121123
na_rep : optional, default is None
122124
a nat format
125+
reso : NPY_DATETIMEUNIT, default NPY_FR_ns
123126

124127
Returns
125128
-------
@@ -141,7 +144,7 @@ def format_array_from_datetime(
141144
# a format based on precision
142145
basic_format = format is None and tz is None
143146
if basic_format:
144-
reso_obj = get_resolution(values)
147+
reso_obj = get_resolution(values, reso=reso)
145148
show_ns = reso_obj == Resolution.RESO_NS
146149
show_us = reso_obj == Resolution.RESO_US
147150
show_ms = reso_obj == Resolution.RESO_MS
@@ -153,7 +156,7 @@ def format_array_from_datetime(
153156
result[i] = na_rep
154157
elif basic_format:
155158

156-
dt64_to_dtstruct(val, &dts)
159+
pandas_datetime_to_datetimestruct(val, reso, &dts)
157160
res = (f'{dts.year}-{dts.month:02d}-{dts.day:02d} '
158161
f'{dts.hour:02d}:{dts.min:02d}:{dts.sec:02d}')
159162

@@ -169,7 +172,7 @@ def format_array_from_datetime(
169172

170173
else:
171174

172-
ts = Timestamp(val, tz=tz)
175+
ts = Timestamp._from_value_and_reso(val, reso=reso, tz=tz)
173176
if format is None:
174177
result[i] = str(ts)
175178
else:

‎pandas/core/arrays/datetimes.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ def _format_native_types(
696696
fmt = get_format_datetime64_from_values(self, date_format)
697697

698698
return tslib.format_array_from_datetime(
699-
self.asi8, tz=self.tz, format=fmt, na_rep=na_rep
699+
self.asi8, tz=self.tz, format=fmt, na_rep=na_rep, reso=self._reso
700700
)
701701

702702
# -----------------------------------------------------------------

‎pandas/io/formats/format.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
NaT,
4343
Timedelta,
4444
Timestamp,
45+
get_unit_from_dtype,
4546
iNaT,
47+
periods_per_day,
4648
)
4749
from pandas._libs.tslibs.nattype import NaTType
4850
from pandas._typing import (
@@ -1738,16 +1740,21 @@ def is_dates_only(values: np.ndarray | DatetimeArray | Index | DatetimeIndex) ->
17381740
if not isinstance(values, Index):
17391741
values = values.ravel()
17401742

1741-
values = DatetimeIndex(values)
1743+
if not isinstance(values, (DatetimeArray, DatetimeIndex)):
1744+
values = DatetimeIndex(values)
1745+
17421746
if values.tz is not None:
17431747
return False
17441748

17451749
values_int = values.asi8
17461750
consider_values = values_int != iNaT
1747-
one_day_nanos = 86400 * 10**9
1748-
even_days = (
1749-
np.logical_and(consider_values, values_int % int(one_day_nanos) != 0).sum() == 0
1750-
)
1751+
# error: Argument 1 to "py_get_unit_from_dtype" has incompatible type
1752+
# "Union[dtype[Any], ExtensionDtype]"; expected "dtype[Any]"
1753+
reso = get_unit_from_dtype(values.dtype) # type: ignore[arg-type]
1754+
ppd = periods_per_day(reso)
1755+
1756+
# TODO: can we reuse is_date_array_normalized? would need a skipna kwd
1757+
even_days = np.logical_and(consider_values, values_int % ppd != 0).sum() == 0
17511758
if even_days:
17521759
return True
17531760
return False

‎pandas/tests/arrays/test_datetimes.py

+14
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ def test_time_date(self, dta_dti, meth):
155155
expected = getattr(dti, meth)
156156
tm.assert_numpy_array_equal(result, expected)
157157

158+
def test_format_native_types(self, unit, reso, dtype, dta_dti):
159+
# In this case we should get the same formatted values with our nano
160+
# version dti._data as we do with the non-nano dta
161+
dta, dti = dta_dti
162+
163+
res = dta._format_native_types()
164+
exp = dti._data._format_native_types()
165+
tm.assert_numpy_array_equal(res, exp)
166+
167+
def test_repr(self, dta_dti, unit):
168+
dta, dti = dta_dti
169+
170+
assert repr(dta) == repr(dti._data).replace("[ns", f"[{unit}")
171+
158172

159173
class TestDatetimeArrayComparisons:
160174
# TODO: merge this into tests/arithmetic/test_datetime64 once it is

‎setup.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,11 @@ def srcpath(name=None, suffix=".pyx", subdir="src"):
492492
"_libs.properties": {"pyxfile": "_libs/properties"},
493493
"_libs.reshape": {"pyxfile": "_libs/reshape", "depends": []},
494494
"_libs.sparse": {"pyxfile": "_libs/sparse", "depends": _pxi_dep["sparse"]},
495-
"_libs.tslib": {"pyxfile": "_libs/tslib", "depends": tseries_depends},
495+
"_libs.tslib": {
496+
"pyxfile": "_libs/tslib",
497+
"depends": tseries_depends,
498+
"sources": ["pandas/_libs/tslibs/src/datetime/np_datetime.c"],
499+
},
496500
"_libs.tslibs.base": {"pyxfile": "_libs/tslibs/base"},
497501
"_libs.tslibs.ccalendar": {"pyxfile": "_libs/tslibs/ccalendar"},
498502
"_libs.tslibs.dtypes": {"pyxfile": "_libs/tslibs/dtypes"},

0 commit comments

Comments
 (0)