Skip to content

Commit e16dd61

Browse files
committed
import!
1 parent 302e4ca commit e16dd61

File tree

7 files changed

+310
-261
lines changed

7 files changed

+310
-261
lines changed

pandas/core/arrays/datetimelike.py

+198-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
from pandas._libs import lib, iNaT, NaT
99
from pandas._libs.tslibs import timezones
10+
from pandas.util._decorators import Appender, cache_readonly
1011
from pandas._libs.tslibs.timedeltas import delta_to_nanoseconds, Timedelta
11-
from pandas._libs.tslibs.timestamps import maybe_integer_op_deprecated
12+
from pandas._libs.tslibs.timestamps import (
13+
maybe_integer_op_deprecated, RoundTo, round_nsint64)
1214
from pandas._libs.tslibs.period import (
1315
Period, DIFFERENT_FREQ_INDEX, IncompatibleFrequency)
1416

@@ -91,7 +93,184 @@ def _get_attributes_dict(self):
9193
return {k: getattr(self, k, None) for k in self._attributes}
9294

9395

94-
class DatetimeLikeArrayMixin(ExtensionOpsMixin, AttributesMixin):
96+
class DatelikeOps(ExtensionOpsMixin):
97+
98+
def strftime(self, date_format):
99+
return self.format(date_format=date_format)
100+
strftime.__doc__ = """
101+
Convert to Index using specified date_format.
102+
103+
Return an Index of formatted strings specified by date_format, which
104+
supports the same string format as the python standard library. Details
105+
of the string format can be found in `python string format doc <{0}>`__
106+
107+
Parameters
108+
----------
109+
date_format : str
110+
Date format string (e.g. "%Y-%m-%d").
111+
112+
Returns
113+
-------
114+
Index
115+
Index of formatted strings
116+
117+
See Also
118+
--------
119+
pandas.to_datetime : Convert the given argument to datetime
120+
DatetimeIndex.normalize : Return DatetimeIndex with times to midnight.
121+
DatetimeIndex.round : Round the DatetimeIndex to the specified freq.
122+
DatetimeIndex.floor : Floor the DatetimeIndex to the specified freq.
123+
124+
Examples
125+
--------
126+
>>> rng = pd.date_range(pd.Timestamp("2018-03-10 09:00"),
127+
... periods=3, freq='s')
128+
>>> rng.strftime('%B %d, %Y, %r')
129+
Index(['March 10, 2018, 09:00:00 AM', 'March 10, 2018, 09:00:01 AM',
130+
'March 10, 2018, 09:00:02 AM'],
131+
dtype='object')
132+
""".format("https://docs.python.org/3/library/datetime.html"
133+
"#strftime-and-strptime-behavior")
134+
135+
136+
class TimelikeOps(object):
137+
""" common ops for TimedeltaIndex/DatetimeIndex, but not PeriodIndex """
138+
139+
_round_doc = (
140+
"""
141+
{op} the data to the specified `freq`.
142+
143+
Parameters
144+
----------
145+
freq : str or Offset
146+
The frequency level to {op} the index to. Must be a fixed
147+
frequency like 'S' (second) not 'ME' (month end). See
148+
:ref:`frequency aliases <timeseries.offset_aliases>` for
149+
a list of possible `freq` values.
150+
ambiguous : 'infer', bool-ndarray, 'NaT', default 'raise'
151+
Only relevant for DatetimeIndex:
152+
153+
- 'infer' will attempt to infer fall dst-transition hours based on
154+
order
155+
- bool-ndarray where True signifies a DST time, False designates
156+
a non-DST time (note that this flag is only applicable for
157+
ambiguous times)
158+
- 'NaT' will return NaT where there are ambiguous times
159+
- 'raise' will raise an AmbiguousTimeError if there are ambiguous
160+
times
161+
162+
.. versionadded:: 0.24.0
163+
nonexistent : 'shift', 'NaT', default 'raise'
164+
A nonexistent time does not exist in a particular timezone
165+
where clocks moved forward due to DST.
166+
167+
- 'shift' will shift the nonexistent time forward to the closest
168+
existing time
169+
- 'NaT' will return NaT where there are nonexistent times
170+
- 'raise' will raise an NonExistentTimeError if there are
171+
nonexistent times
172+
173+
.. versionadded:: 0.24.0
174+
175+
Returns
176+
-------
177+
DatetimeIndex, TimedeltaIndex, or Series
178+
Index of the same type for a DatetimeIndex or TimedeltaIndex,
179+
or a Series with the same index for a Series.
180+
181+
Raises
182+
------
183+
ValueError if the `freq` cannot be converted.
184+
185+
Examples
186+
--------
187+
**DatetimeIndex**
188+
189+
>>> rng = pd.date_range('1/1/2018 11:59:00', periods=3, freq='min')
190+
>>> rng
191+
DatetimeIndex(['2018-01-01 11:59:00', '2018-01-01 12:00:00',
192+
'2018-01-01 12:01:00'],
193+
dtype='datetime64[ns]', freq='T')
194+
""")
195+
196+
_round_example = (
197+
""">>> rng.round('H')
198+
DatetimeIndex(['2018-01-01 12:00:00', '2018-01-01 12:00:00',
199+
'2018-01-01 12:00:00'],
200+
dtype='datetime64[ns]', freq=None)
201+
202+
**Series**
203+
204+
>>> pd.Series(rng).dt.round("H")
205+
0 2018-01-01 12:00:00
206+
1 2018-01-01 12:00:00
207+
2 2018-01-01 12:00:00
208+
dtype: datetime64[ns]
209+
""")
210+
211+
_floor_example = (
212+
""">>> rng.floor('H')
213+
DatetimeIndex(['2018-01-01 11:00:00', '2018-01-01 12:00:00',
214+
'2018-01-01 12:00:00'],
215+
dtype='datetime64[ns]', freq=None)
216+
217+
**Series**
218+
219+
>>> pd.Series(rng).dt.floor("H")
220+
0 2018-01-01 11:00:00
221+
1 2018-01-01 12:00:00
222+
2 2018-01-01 12:00:00
223+
dtype: datetime64[ns]
224+
"""
225+
)
226+
227+
_ceil_example = (
228+
""">>> rng.ceil('H')
229+
DatetimeIndex(['2018-01-01 12:00:00', '2018-01-01 12:00:00',
230+
'2018-01-01 13:00:00'],
231+
dtype='datetime64[ns]', freq=None)
232+
233+
**Series**
234+
235+
>>> pd.Series(rng).dt.ceil("H")
236+
0 2018-01-01 12:00:00
237+
1 2018-01-01 12:00:00
238+
2 2018-01-01 13:00:00
239+
dtype: datetime64[ns]
240+
"""
241+
)
242+
243+
def _round(self, freq, mode, ambiguous, nonexistent):
244+
# round the local times
245+
# TODO
246+
values = _ensure_datetimelike_to_i8(self)
247+
result = round_nsint64(values, mode, freq)
248+
result = self._maybe_mask_results(result, fill_value=NaT)
249+
250+
attribs = self._get_attributes_dict()
251+
attribs['freq'] = None
252+
if 'tz' in attribs:
253+
attribs['tz'] = None
254+
return self._ensure_localized(
255+
self._shallow_copy(result, **attribs), ambiguous, nonexistent
256+
)
257+
258+
@Appender((_round_doc + _round_example).format(op="round"))
259+
def round(self, freq, ambiguous='raise', nonexistent='raise'):
260+
return self._round(
261+
freq, RoundTo.NEAREST_HALF_EVEN, ambiguous, nonexistent
262+
)
263+
264+
@Appender((_round_doc + _floor_example).format(op="floor"))
265+
def floor(self, freq, ambiguous='raise', nonexistent='raise'):
266+
return self._round(freq, RoundTo.MINUS_INFTY, ambiguous, nonexistent)
267+
268+
@Appender((_round_doc + _ceil_example).format(op="ceil"))
269+
def ceil(self, freq, ambiguous='raise', nonexistent='raise'):
270+
return self._round(freq, RoundTo.PLUS_INFTY, ambiguous, nonexistent)
271+
272+
273+
class DatetimeLikeArrayMixin(DatelikeOps, TimelikeOps, AttributesMixin):
95274
"""
96275
Shared Base/Mixin class for DatetimeArray, TimedeltaArray, PeriodArray
97276
@@ -103,6 +282,23 @@ class DatetimeLikeArrayMixin(ExtensionOpsMixin, AttributesMixin):
103282
_generate_range
104283
"""
105284

285+
# define my properties & methods for delegation
286+
_bool_ops = ['is_month_start', 'is_month_end',
287+
'is_quarter_start', 'is_quarter_end', 'is_year_start',
288+
'is_year_end', 'is_leap_year']
289+
_object_ops = ['weekday_name', 'freq', 'tz']
290+
_field_ops = ['year', 'month', 'day', 'hour', 'minute', 'second',
291+
'weekofyear', 'week', 'weekday', 'dayofweek',
292+
'dayofyear', 'quarter', 'days_in_month',
293+
'daysinmonth', 'microsecond',
294+
'nanosecond']
295+
_other_ops = ['date', 'time', 'timetz']
296+
_datetimelike_ops = _field_ops + _object_ops + _bool_ops + _other_ops
297+
_datetimelike_methods = ['to_period', 'tz_localize',
298+
'tz_convert',
299+
'normalize', 'strftime', 'round', 'floor',
300+
'ceil', 'month_name', 'day_name',]
301+
106302
@property
107303
def _box_func(self):
108304
"""

pandas/core/arrays/timedeltas.py

+8
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ def wrapper(self, other):
109109

110110
class TimedeltaArrayMixin(dtl.DatetimeLikeArrayMixin):
111111
_typ = "timedeltaarray"
112+
# define my properties & methods for delegation
113+
_other_ops = []
114+
_bool_ops = []
115+
_object_ops = ['freq']
116+
_field_ops = ['days', 'seconds', 'microseconds', 'nanoseconds']
117+
_datetimelike_ops = _field_ops + _object_ops + _bool_ops
118+
_datetimelike_methods = ["to_pytimedelta", "total_seconds",
119+
"round", "floor", "ceil"]
112120

113121
@property
114122
def _box_func(self):

pandas/core/indexes/accessors.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414
from pandas.core.accessor import PandasDelegate, delegate_names
1515
from pandas.core.base import NoNewAttributesMixin, PandasObject
1616
from pandas.core.indexes.datetimes import DatetimeIndex
17-
from pandas.core.indexes.period import PeriodArray
17+
from pandas.core.arrays import (
18+
PeriodArray,
19+
DatetimeArrayMixin as DatetimeArray,
20+
TimedeltaArrayMixin as TimedeltaArray,
21+
)
1822
from pandas.core.indexes.timedeltas import TimedeltaIndex
1923
from pandas.core.algorithms import take_1d
2024

@@ -110,11 +114,11 @@ def _delegate_method(self, name, *args, **kwargs):
110114
return result
111115

112116

113-
@delegate_names(delegate=DatetimeIndex,
114-
accessors=DatetimeIndex._datetimelike_ops,
117+
@delegate_names(delegate=DatetimeArray,
118+
accessors=DatetimeArray._datetimelike_ops,
115119
typ="property")
116-
@delegate_names(delegate=DatetimeIndex,
117-
accessors=DatetimeIndex._datetimelike_methods,
120+
@delegate_names(delegate=DatetimeArray,
121+
accessors=DatetimeArray._datetimelike_methods,
118122
typ="method")
119123
class DatetimeProperties(Properties):
120124
"""
@@ -181,11 +185,11 @@ def freq(self):
181185
return self._get_values().inferred_freq
182186

183187

184-
@delegate_names(delegate=TimedeltaIndex,
185-
accessors=TimedeltaIndex._datetimelike_ops,
188+
@delegate_names(delegate=TimedeltaArray,
189+
accessors=TimedeltaArray._datetimelike_ops,
186190
typ="property")
187-
@delegate_names(delegate=TimedeltaIndex,
188-
accessors=TimedeltaIndex._datetimelike_methods,
191+
@delegate_names(delegate=TimedeltaArray,
192+
accessors=TimedeltaArray._datetimelike_methods,
189193
typ="method")
190194
class TimedeltaProperties(Properties):
191195
"""

0 commit comments

Comments
 (0)