Skip to content

Commit 809d9b7

Browse files
authored
API: date_range, timedelta_range infer unit from start/end/freq (#63146)
1 parent 1b5b02c commit 809d9b7

File tree

127 files changed

+743
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+743
-438
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,7 @@ Other API changes
748748
the dtype of the resulting Index (:issue:`60797`)
749749
- :class:`IncompatibleFrequency` now subclasses ``TypeError`` instead of ``ValueError``. As a result, joins with mismatched frequencies now cast to object like other non-comparable joins, and arithmetic with indexes with mismatched frequencies align (:issue:`55782`)
750750
- :class:`Series` "flex" methods like :meth:`Series.add` no longer allow passing a :class:`DataFrame` for ``other``; use the DataFrame reversed method instead (:issue:`46179`)
751+
- :func:`date_range` and :func:`timedelta_range` no longer default to ``unit="ns"``, instead will infer a unit from the ``start``, ``end``, and ``freq`` parameters. Explicitly specify a desired ``unit`` to override these (:issue:`59031`)
751752
- :meth:`CategoricalIndex.append` no longer attempts to cast different-dtype indexes to the caller's dtype (:issue:`41626`)
752753
- :meth:`ExtensionDtype.construct_array_type` is now a regular method instead of a ``classmethod`` (:issue:`58663`)
753754
- Arithmetic operations between a :class:`Series`, :class:`Index`, or :class:`ExtensionArray` with a ``list`` now consistently wrap that list with an array equivalent to ``Series(my_list).array``. To do any other kind of type inference or casting, do so explicitly before operating (:issue:`62552`)

pandas/_libs/tslibs/np_datetime.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ class OutOfBoundsTimedelta(ValueError):
208208
209209
Examples
210210
--------
211-
>>> pd.date_range(start="1/1/1700", freq="B", periods=100000)
211+
>>> pd.date_range(start="1/1/1700", freq="B", periods=100000, unit="ns")
212212
Traceback (most recent call last):
213213
OutOfBoundsTimedelta: Cannot cast 139999 days 00:00:00
214214
to unit='ns' without overflow.

pandas/core/arrays/datetimelike.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,7 +1649,7 @@ def mean(self, *, skipna: bool = True, axis: AxisInt | None = 0):
16491649
>>> idx = pd.date_range("2001-01-01 00:00", periods=3)
16501650
>>> idx
16511651
DatetimeIndex(['2001-01-01', '2001-01-02', '2001-01-03'],
1652-
dtype='datetime64[ns]', freq='D')
1652+
dtype='datetime64[us]', freq='D')
16531653
>>> idx.mean()
16541654
Timestamp('2001-01-02 00:00:00')
16551655
@@ -1900,21 +1900,21 @@ def strftime(self, date_format: str) -> npt.NDArray[np.object_]:
19001900
>>> rng
19011901
DatetimeIndex(['2018-01-01 11:59:00', '2018-01-01 12:00:00',
19021902
'2018-01-01 12:01:00'],
1903-
dtype='datetime64[ns]', freq='min')
1903+
dtype='datetime64[us]', freq='min')
19041904
"""
19051905

19061906
_round_example = """>>> rng.round('h')
19071907
DatetimeIndex(['2018-01-01 12:00:00', '2018-01-01 12:00:00',
19081908
'2018-01-01 12:00:00'],
1909-
dtype='datetime64[ns]', freq=None)
1909+
dtype='datetime64[us]', freq=None)
19101910
19111911
**Series**
19121912
19131913
>>> pd.Series(rng).dt.round("h")
19141914
0 2018-01-01 12:00:00
19151915
1 2018-01-01 12:00:00
19161916
2 2018-01-01 12:00:00
1917-
dtype: datetime64[ns]
1917+
dtype: datetime64[us]
19181918
19191919
When rounding near a daylight savings time transition, use ``ambiguous`` or
19201920
``nonexistent`` to control how the timestamp should be re-localized.
@@ -1933,15 +1933,15 @@ def strftime(self, date_format: str) -> npt.NDArray[np.object_]:
19331933
_floor_example = """>>> rng.floor('h')
19341934
DatetimeIndex(['2018-01-01 11:00:00', '2018-01-01 12:00:00',
19351935
'2018-01-01 12:00:00'],
1936-
dtype='datetime64[ns]', freq=None)
1936+
dtype='datetime64[us]', freq=None)
19371937
19381938
**Series**
19391939
19401940
>>> pd.Series(rng).dt.floor("h")
19411941
0 2018-01-01 11:00:00
19421942
1 2018-01-01 12:00:00
19431943
2 2018-01-01 12:00:00
1944-
dtype: datetime64[ns]
1944+
dtype: datetime64[us]
19451945
19461946
When rounding near a daylight savings time transition, use ``ambiguous`` or
19471947
``nonexistent`` to control how the timestamp should be re-localized.
@@ -1960,15 +1960,15 @@ def strftime(self, date_format: str) -> npt.NDArray[np.object_]:
19601960
_ceil_example = """>>> rng.ceil('h')
19611961
DatetimeIndex(['2018-01-01 12:00:00', '2018-01-01 12:00:00',
19621962
'2018-01-01 13:00:00'],
1963-
dtype='datetime64[ns]', freq=None)
1963+
dtype='datetime64[us]', freq=None)
19641964
19651965
**Series**
19661966
19671967
>>> pd.Series(rng).dt.ceil("h")
19681968
0 2018-01-01 12:00:00
19691969
1 2018-01-01 12:00:00
19701970
2 2018-01-01 13:00:00
1971-
dtype: datetime64[ns]
1971+
dtype: datetime64[us]
19721972
19731973
When rounding near a daylight savings time transition, use ``ambiguous`` or
19741974
``nonexistent`` to control how the timestamp should be re-localized.
@@ -2018,7 +2018,7 @@ def freq(self):
20182018
'2022-02-22 06:22:22-06:00', '2022-02-22 07:22:22-06:00',
20192019
'2022-02-22 08:22:22-06:00', '2022-02-22 09:22:22-06:00',
20202020
'2022-02-22 10:22:22-06:00', '2022-02-22 11:22:22-06:00'],
2021-
dtype='datetime64[ns, America/Chicago]', freq='h')
2021+
dtype='datetime64[us, America/Chicago]', freq='h')
20222022
>>> datetimeindex.freq
20232023
<Hour>
20242024
"""

pandas/core/arrays/datetimes.py

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -913,13 +913,13 @@ def tz_convert(self, tz) -> Self:
913913
DatetimeIndex(['2014-08-01 09:00:00+02:00',
914914
'2014-08-01 10:00:00+02:00',
915915
'2014-08-01 11:00:00+02:00'],
916-
dtype='datetime64[ns, Europe/Berlin]', freq='h')
916+
dtype='datetime64[us, Europe/Berlin]', freq='h')
917917
918918
>>> dti.tz_convert(None)
919919
DatetimeIndex(['2014-08-01 07:00:00',
920920
'2014-08-01 08:00:00',
921921
'2014-08-01 09:00:00'],
922-
dtype='datetime64[ns]', freq='h')
922+
dtype='datetime64[us]', freq='h')
923923
""" # noqa: E501
924924
tz = timezones.maybe_get_tz(tz)
925925

@@ -1010,7 +1010,7 @@ def tz_localize(
10101010
>>> tz_naive
10111011
DatetimeIndex(['2018-03-01 09:00:00', '2018-03-02 09:00:00',
10121012
'2018-03-03 09:00:00'],
1013-
dtype='datetime64[ns]', freq='D')
1013+
dtype='datetime64[us]', freq='D')
10141014
10151015
Localize DatetimeIndex in US/Eastern time zone:
10161016
@@ -1019,15 +1019,15 @@ def tz_localize(
10191019
DatetimeIndex(['2018-03-01 09:00:00-05:00',
10201020
'2018-03-02 09:00:00-05:00',
10211021
'2018-03-03 09:00:00-05:00'],
1022-
dtype='datetime64[ns, US/Eastern]', freq=None)
1022+
dtype='datetime64[us, US/Eastern]', freq=None)
10231023
10241024
With the ``tz=None``, we can remove the time zone information
10251025
while keeping the local time (not converted to UTC):
10261026
10271027
>>> tz_aware.tz_localize(None)
10281028
DatetimeIndex(['2018-03-01 09:00:00', '2018-03-02 09:00:00',
10291029
'2018-03-03 09:00:00'],
1030-
dtype='datetime64[ns]', freq=None)
1030+
dtype='datetime64[us]', freq=None)
10311031
10321032
Be careful with DST changes. When there is sequential data, pandas can
10331033
infer the DST time:
@@ -1180,12 +1180,12 @@ def normalize(self) -> Self:
11801180
DatetimeIndex(['2014-08-01 10:00:00+05:30',
11811181
'2014-08-01 11:00:00+05:30',
11821182
'2014-08-01 12:00:00+05:30'],
1183-
dtype='datetime64[ns, Asia/Calcutta]', freq='h')
1183+
dtype='datetime64[us, Asia/Calcutta]', freq='h')
11841184
>>> idx.normalize()
11851185
DatetimeIndex(['2014-08-01 00:00:00+05:30',
11861186
'2014-08-01 00:00:00+05:30',
11871187
'2014-08-01 00:00:00+05:30'],
1188-
dtype='datetime64[ns, Asia/Calcutta]', freq=None)
1188+
dtype='datetime64[us, Asia/Calcutta]', freq=None)
11891189
"""
11901190
new_values = normalize_i8_timestamps(self.asi8, self.tz, reso=self._creso)
11911191
dt64_values = new_values.view(self._ndarray.dtype)
@@ -1309,7 +1309,7 @@ def month_name(self, locale=None) -> npt.NDArray[np.object_]:
13091309
0 2018-01-31
13101310
1 2018-02-28
13111311
2 2018-03-31
1312-
dtype: datetime64[ns]
1312+
dtype: datetime64[us]
13131313
>>> s.dt.month_name()
13141314
0 January
13151315
1 February
@@ -1319,7 +1319,7 @@ def month_name(self, locale=None) -> npt.NDArray[np.object_]:
13191319
>>> idx = pd.date_range(start="2018-01", freq="ME", periods=3)
13201320
>>> idx
13211321
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31'],
1322-
dtype='datetime64[ns]', freq='ME')
1322+
dtype='datetime64[us]', freq='ME')
13231323
>>> idx.month_name()
13241324
Index(['January', 'February', 'March'], dtype='str')
13251325
@@ -1330,7 +1330,7 @@ def month_name(self, locale=None) -> npt.NDArray[np.object_]:
13301330
>>> idx = pd.date_range(start="2018-01", freq="ME", periods=3)
13311331
>>> idx
13321332
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31'],
1333-
dtype='datetime64[ns]', freq='ME')
1333+
dtype='datetime64[us]', freq='ME')
13341334
>>> idx.month_name(locale="pt_BR.utf8") # doctest: +SKIP
13351335
Index(['Janeiro', 'Fevereiro', 'Março'], dtype='str')
13361336
"""
@@ -1377,7 +1377,7 @@ def day_name(self, locale=None) -> npt.NDArray[np.object_]:
13771377
0 2018-01-01
13781378
1 2018-01-02
13791379
2 2018-01-03
1380-
dtype: datetime64[ns]
1380+
dtype: datetime64[us]
13811381
>>> s.dt.day_name()
13821382
0 Monday
13831383
1 Tuesday
@@ -1387,7 +1387,7 @@ def day_name(self, locale=None) -> npt.NDArray[np.object_]:
13871387
>>> idx = pd.date_range(start="2018-01-01", freq="D", periods=3)
13881388
>>> idx
13891389
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03'],
1390-
dtype='datetime64[ns]', freq='D')
1390+
dtype='datetime64[us]', freq='D')
13911391
>>> idx.day_name()
13921392
Index(['Monday', 'Tuesday', 'Wednesday'], dtype='str')
13931393
@@ -1398,7 +1398,7 @@ def day_name(self, locale=None) -> npt.NDArray[np.object_]:
13981398
>>> idx = pd.date_range(start="2018-01-01", freq="D", periods=3)
13991399
>>> idx
14001400
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03'],
1401-
dtype='datetime64[ns]', freq='D')
1401+
dtype='datetime64[us]', freq='D')
14021402
>>> idx.day_name(locale="pt_BR.utf8") # doctest: +SKIP
14031403
Index(['Segunda', 'Terça', 'Quarta'], dtype='str')
14041404
"""
@@ -1611,7 +1611,7 @@ def isocalendar(self) -> DataFrame:
16111611
0 2000-12-31
16121612
1 2001-12-31
16131613
2 2002-12-31
1614-
dtype: datetime64[ns]
1614+
dtype: datetime64[us]
16151615
>>> datetime_series.dt.year
16161616
0 2000
16171617
1 2001
@@ -1639,7 +1639,7 @@ def isocalendar(self) -> DataFrame:
16391639
0 2000-01-31
16401640
1 2000-02-29
16411641
2 2000-03-31
1642-
dtype: datetime64[ns]
1642+
dtype: datetime64[us]
16431643
>>> datetime_series.dt.month
16441644
0 1
16451645
1 2
@@ -1668,7 +1668,7 @@ def isocalendar(self) -> DataFrame:
16681668
0 2000-01-01
16691669
1 2000-01-02
16701670
2 2000-01-03
1671-
dtype: datetime64[ns]
1671+
dtype: datetime64[us]
16721672
>>> datetime_series.dt.day
16731673
0 1
16741674
1 2
@@ -1697,7 +1697,7 @@ def isocalendar(self) -> DataFrame:
16971697
0 2000-01-01 00:00:00
16981698
1 2000-01-01 01:00:00
16991699
2 2000-01-01 02:00:00
1700-
dtype: datetime64[ns]
1700+
dtype: datetime64[us]
17011701
>>> datetime_series.dt.hour
17021702
0 0
17031703
1 1
@@ -1725,7 +1725,7 @@ def isocalendar(self) -> DataFrame:
17251725
0 2000-01-01 00:00:00
17261726
1 2000-01-01 00:01:00
17271727
2 2000-01-01 00:02:00
1728-
dtype: datetime64[ns]
1728+
dtype: datetime64[us]
17291729
>>> datetime_series.dt.minute
17301730
0 0
17311731
1 1
@@ -1754,7 +1754,7 @@ def isocalendar(self) -> DataFrame:
17541754
0 2000-01-01 00:00:00
17551755
1 2000-01-01 00:00:01
17561756
2 2000-01-01 00:00:02
1757-
dtype: datetime64[ns]
1757+
dtype: datetime64[us]
17581758
>>> datetime_series.dt.second
17591759
0 0
17601760
1 1
@@ -1782,7 +1782,7 @@ def isocalendar(self) -> DataFrame:
17821782
0 2000-01-01 00:00:00.000000
17831783
1 2000-01-01 00:00:00.000001
17841784
2 2000-01-01 00:00:00.000002
1785-
dtype: datetime64[ns]
1785+
dtype: datetime64[us]
17861786
>>> datetime_series.dt.microsecond
17871787
0 0
17881788
1 1
@@ -1982,7 +1982,7 @@ def isocalendar(self) -> DataFrame:
19821982
0 2018-02-27
19831983
1 2018-02-28
19841984
2 2018-03-01
1985-
dtype: datetime64[ns]
1985+
dtype: datetime64[us]
19861986
>>> s.dt.is_month_start
19871987
0 False
19881988
1 False
@@ -2044,7 +2044,7 @@ def isocalendar(self) -> DataFrame:
20442044
>>> idx = pd.date_range('2017-03-30', periods=4)
20452045
>>> idx
20462046
DatetimeIndex(['2017-03-30', '2017-03-31', '2017-04-01', '2017-04-02'],
2047-
dtype='datetime64[ns]', freq='D')
2047+
dtype='datetime64[us]', freq='D')
20482048
20492049
>>> idx.is_quarter_start
20502050
array([False, False, True, False])
@@ -2086,7 +2086,7 @@ def isocalendar(self) -> DataFrame:
20862086
>>> idx = pd.date_range('2017-03-30', periods=4)
20872087
>>> idx
20882088
DatetimeIndex(['2017-03-30', '2017-03-31', '2017-04-01', '2017-04-02'],
2089-
dtype='datetime64[ns]', freq='D')
2089+
dtype='datetime64[us]', freq='D')
20902090
20912091
>>> idx.is_quarter_end
20922092
array([False, True, False, False])
@@ -2119,7 +2119,7 @@ def isocalendar(self) -> DataFrame:
21192119
0 2017-12-30
21202120
1 2017-12-31
21212121
2 2018-01-01
2122-
dtype: datetime64[ns]
2122+
dtype: datetime64[us]
21232123
21242124
>>> dates.dt.is_year_start
21252125
0 False
@@ -2130,7 +2130,7 @@ def isocalendar(self) -> DataFrame:
21302130
>>> idx = pd.date_range("2017-12-30", periods=3)
21312131
>>> idx
21322132
DatetimeIndex(['2017-12-30', '2017-12-31', '2018-01-01'],
2133-
dtype='datetime64[ns]', freq='D')
2133+
dtype='datetime64[us]', freq='D')
21342134
21352135
>>> idx.is_year_start
21362136
array([False, False, True])
@@ -2144,7 +2144,7 @@ def isocalendar(self) -> DataFrame:
21442144
1 2022-01-03
21452145
2 2023-01-02
21462146
3 2024-01-01
2147-
dtype: datetime64[ns]
2147+
dtype: datetime64[us]
21482148
21492149
>>> dates.dt.is_year_start
21502150
0 True
@@ -2156,7 +2156,7 @@ def isocalendar(self) -> DataFrame:
21562156
>>> idx = pd.date_range("2020-10-30", periods=4, freq="BYS")
21572157
>>> idx
21582158
DatetimeIndex(['2021-01-01', '2022-01-03', '2023-01-02', '2024-01-01'],
2159-
dtype='datetime64[ns]', freq='BYS-JAN')
2159+
dtype='datetime64[us]', freq='BYS-JAN')
21602160
21612161
>>> idx.is_year_start
21622162
array([ True, True, True, True])
@@ -2189,7 +2189,7 @@ def isocalendar(self) -> DataFrame:
21892189
0 2017-12-30
21902190
1 2017-12-31
21912191
2 2018-01-01
2192-
dtype: datetime64[ns]
2192+
dtype: datetime64[us]
21932193
21942194
>>> dates.dt.is_year_end
21952195
0 False
@@ -2200,7 +2200,7 @@ def isocalendar(self) -> DataFrame:
22002200
>>> idx = pd.date_range("2017-12-30", periods=3)
22012201
>>> idx
22022202
DatetimeIndex(['2017-12-30', '2017-12-31', '2018-01-01'],
2203-
dtype='datetime64[ns]', freq='D')
2203+
dtype='datetime64[us]', freq='D')
22042204
22052205
>>> idx.is_year_end
22062206
array([False, True, False])
@@ -2237,7 +2237,7 @@ def isocalendar(self) -> DataFrame:
22372237
>>> idx = pd.date_range("2012-01-01", "2015-01-01", freq="YE")
22382238
>>> idx
22392239
DatetimeIndex(['2012-12-31', '2013-12-31', '2014-12-31'],
2240-
dtype='datetime64[ns]', freq='YE-DEC')
2240+
dtype='datetime64[us]', freq='YE-DEC')
22412241
>>> idx.is_leap_year
22422242
array([ True, False, False])
22432243
@@ -2246,7 +2246,7 @@ def isocalendar(self) -> DataFrame:
22462246
0 2012-12-31
22472247
1 2013-12-31
22482248
2 2014-12-31
2249-
dtype: datetime64[ns]
2249+
dtype: datetime64[us]
22502250
>>> dates_series.dt.is_leap_year
22512251
0 True
22522252
1 False
@@ -2380,7 +2380,7 @@ def std(
23802380
>>> idx = pd.date_range("2001-01-01 00:00", periods=3)
23812381
>>> idx
23822382
DatetimeIndex(['2001-01-01', '2001-01-02', '2001-01-03'],
2383-
dtype='datetime64[ns]', freq='D')
2383+
dtype='datetime64[us]', freq='D')
23842384
>>> idx.std()
23852385
Timedelta('1 days 00:00:00')
23862386
"""

pandas/core/generic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6446,7 +6446,7 @@ def astype(
64466446
0 2020-01-01
64476447
1 2020-01-02
64486448
2 2020-01-03
6449-
dtype: datetime64[ns]
6449+
dtype: datetime64[us]
64506450
"""
64516451
self._check_copy_deprecation(copy)
64526452
if is_dict_like(dtype):

0 commit comments

Comments
 (0)