Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/indexes/accessors.py: 40%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

188 statements  

1""" 

2datetimelike delegation 

3""" 

4 

5from __future__ import annotations 

6 

7from typing import ( 

8 TYPE_CHECKING, 

9 NoReturn, 

10 cast, 

11) 

12import warnings 

13 

14import numpy as np 

15 

16from pandas._libs import lib 

17from pandas.errors import Pandas4Warning 

18from pandas.util._exceptions import find_stack_level 

19 

20from pandas.core.dtypes.common import ( 

21 is_integer_dtype, 

22 is_list_like, 

23) 

24from pandas.core.dtypes.dtypes import ( 

25 ArrowDtype, 

26 CategoricalDtype, 

27 DatetimeTZDtype, 

28 PeriodDtype, 

29) 

30from pandas.core.dtypes.generic import ABCSeries 

31 

32from pandas.core.accessor import ( 

33 PandasDelegate, 

34 delegate_names, 

35) 

36from pandas.core.arrays import ( 

37 DatetimeArray, 

38 PeriodArray, 

39 TimedeltaArray, 

40) 

41from pandas.core.arrays.arrow.array import ArrowExtensionArray 

42from pandas.core.base import ( 

43 NoNewAttributesMixin, 

44 PandasObject, 

45) 

46from pandas.core.indexes.datetimes import DatetimeIndex 

47from pandas.core.indexes.timedeltas import TimedeltaIndex 

48 

49from pandas.tseries import frequencies 

50 

51if TYPE_CHECKING: 

52 from pandas import ( 

53 DataFrame, 

54 Series, 

55 ) 

56 

57 

58class Properties(PandasDelegate, PandasObject, NoNewAttributesMixin): 

59 _hidden_attrs = PandasObject._hidden_attrs | { 

60 "orig", 

61 "name", 

62 } 

63 

64 def __init__(self, data: Series, orig) -> None: 

65 if not isinstance(data, ABCSeries): 

66 raise TypeError( 

67 f"cannot convert an object of type {type(data)} to a datetimelike index" 

68 ) 

69 

70 self._parent = data 

71 self.orig = orig 

72 self.name = getattr(data, "name", None) 

73 self._freeze() 

74 

75 def _get_values(self): 

76 data = self._parent 

77 if lib.is_np_dtype(data.dtype, "M"): 

78 return DatetimeIndex(data, copy=False, name=self.name) 

79 

80 elif isinstance(data.dtype, DatetimeTZDtype): 

81 return DatetimeIndex(data, copy=False, name=self.name) 

82 

83 elif lib.is_np_dtype(data.dtype, "m"): 

84 return TimedeltaIndex(data, copy=False, name=self.name) 

85 

86 elif isinstance(data.dtype, PeriodDtype): 

87 return PeriodArray(data, copy=False) 

88 

89 raise TypeError( 

90 f"cannot convert an object of type {type(data)} to a datetimelike index" 

91 ) 

92 

93 def _delegate_property_get(self, name: str): 

94 from pandas import Series 

95 

96 values = self._get_values() 

97 

98 result = getattr(values, name) 

99 

100 # maybe need to upcast (ints) 

101 if isinstance(result, np.ndarray): 

102 if is_integer_dtype(result): 

103 result = result.astype("int64") 

104 elif not is_list_like(result): 

105 return result 

106 

107 result = np.asarray(result) 

108 

109 if self.orig is not None: 

110 index = self.orig.index 

111 else: 

112 index = self._parent.index 

113 # return the result as a Series 

114 return Series(result, index=index, name=self.name).__finalize__(self._parent) 

115 

116 def _delegate_property_set(self, name: str, value, *args, **kwargs) -> NoReturn: 

117 raise ValueError( 

118 "modifications to a property of a datetimelike object are not supported. " 

119 "Change values on the original." 

120 ) 

121 

122 def _delegate_method(self, name: str, *args, **kwargs): 

123 from pandas import Series 

124 

125 values = self._get_values() 

126 

127 method = getattr(values, name) 

128 result = method(*args, **kwargs) 

129 

130 if not is_list_like(result): 

131 return result 

132 

133 return Series(result, index=self._parent.index, name=self.name).__finalize__( 

134 self._parent 

135 ) 

136 

137 

138@delegate_names( 

139 delegate=ArrowExtensionArray, 

140 accessors=TimedeltaArray._datetimelike_ops, 

141 typ="property", 

142 accessor_mapping=lambda x: f"_dt_{x}", 

143 raise_on_missing=False, 

144) 

145@delegate_names( 

146 delegate=ArrowExtensionArray, 

147 accessors=TimedeltaArray._datetimelike_methods, 

148 typ="method", 

149 accessor_mapping=lambda x: f"_dt_{x}", 

150 raise_on_missing=False, 

151) 

152@delegate_names( 

153 delegate=ArrowExtensionArray, 

154 accessors=[ 

155 *DatetimeArray._datetimelike_ops, 

156 # deprecated, but should still work 

157 "dayofweek", 

158 "dayofyear", 

159 "daysinmonth", 

160 "weekday", 

161 ], 

162 typ="property", 

163 accessor_mapping=lambda x: f"_dt_{x}", 

164 raise_on_missing=False, 

165) 

166@delegate_names( 

167 delegate=ArrowExtensionArray, 

168 accessors=DatetimeArray._datetimelike_methods, 

169 typ="method", 

170 accessor_mapping=lambda x: f"_dt_{x}", 

171 raise_on_missing=False, 

172) 

173class ArrowTemporalProperties(PandasDelegate, PandasObject, NoNewAttributesMixin): 

174 def __init__(self, data: Series, orig) -> None: 

175 if not isinstance(data, ABCSeries): 

176 raise TypeError( 

177 f"cannot convert an object of type {type(data)} to a datetimelike index" 

178 ) 

179 

180 self._parent = data 

181 self._orig = orig 

182 self._freeze() 

183 

184 def _delegate_property_get(self, name: str): 

185 if not hasattr(self._parent.array, f"_dt_{name}"): 

186 raise NotImplementedError( 

187 f"dt.{name} is not supported for {self._parent.dtype}" 

188 ) 

189 result = getattr(self._parent.array, f"_dt_{name}") 

190 

191 if not is_list_like(result): 

192 return result 

193 

194 if self._orig is not None: 

195 index = self._orig.index 

196 else: 

197 index = self._parent.index 

198 # return the result as a Series, which is by definition a copy 

199 result = type(self._parent)( 

200 result, index=index, name=self._parent.name 

201 ).__finalize__(self._parent) 

202 

203 return result 

204 

205 def _delegate_method(self, name: str, *args, **kwargs): 

206 if not hasattr(self._parent.array, f"_dt_{name}"): 

207 raise NotImplementedError( 

208 f"dt.{name} is not supported for {self._parent.dtype}" 

209 ) 

210 

211 result = getattr(self._parent.array, f"_dt_{name}")(*args, **kwargs) 

212 

213 if self._orig is not None: 

214 index = self._orig.index 

215 else: 

216 index = self._parent.index 

217 # return the result as a Series, which is by definition a copy 

218 result = type(self._parent)( 

219 result, index=index, name=self._parent.name 

220 ).__finalize__(self._parent) 

221 

222 return result 

223 

224 def to_pytimedelta(self): 

225 # GH 57463 

226 warnings.warn( 

227 f"The behavior of {type(self).__name__}.to_pytimedelta is deprecated, " 

228 "in a future version this will return a Series containing python " 

229 "datetime.timedelta objects instead of an ndarray. To retain the " 

230 "old behavior, call `np.array` on the result", 

231 Pandas4Warning, 

232 stacklevel=find_stack_level(), 

233 ) 

234 return cast("ArrowExtensionArray", self._parent.array)._dt_to_pytimedelta() 

235 

236 def to_pydatetime(self) -> Series: 

237 # GH#20306 

238 result = cast("ArrowExtensionArray", self._parent.array)._dt_to_pydatetime() 

239 result.index = self._parent.index 

240 result.name = self._parent.name 

241 return result 

242 

243 def isocalendar(self) -> DataFrame: 

244 from pandas import DataFrame 

245 

246 result = ( 

247 cast("ArrowExtensionArray", self._parent.array) 

248 ._dt_isocalendar() 

249 ._pa_array.combine_chunks() 

250 ) 

251 iso_calendar_df = DataFrame( 

252 { 

253 col: type(self._parent.array)(result.field(i)) # type: ignore[call-arg] 

254 for i, col in enumerate(["year", "week", "day"]) 

255 }, 

256 index=self._parent.index, 

257 ) 

258 return iso_calendar_df 

259 

260 @property 

261 def components(self) -> DataFrame: 

262 from pandas import DataFrame 

263 

264 return ( 

265 DataFrame(cast("ArrowExtensionArray", self._parent.array)._dt_components) 

266 .set_index(self._parent.index) 

267 .__finalize__(self._parent) 

268 ) 

269 

270 

271@delegate_names( 

272 delegate=DatetimeArray, 

273 accessors=[*DatetimeArray._datetimelike_ops, "unit"], 

274 typ="property", 

275) 

276@delegate_names( 

277 delegate=DatetimeArray, 

278 accessors=[*DatetimeArray._datetimelike_methods, "as_unit"], 

279 typ="method", 

280) 

281class DatetimeProperties(Properties): 

282 """ 

283 Accessor object for datetimelike properties of the Series values. 

284 

285 Examples 

286 -------- 

287 >>> seconds_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="s")) 

288 >>> seconds_series 

289 0 2000-01-01 00:00:00 

290 1 2000-01-01 00:00:01 

291 2 2000-01-01 00:00:02 

292 dtype: datetime64[us] 

293 >>> seconds_series.dt.second 

294 0 0 

295 1 1 

296 2 2 

297 dtype: int32 

298 

299 >>> hours_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="h")) 

300 >>> hours_series 

301 0 2000-01-01 00:00:00 

302 1 2000-01-01 01:00:00 

303 2 2000-01-01 02:00:00 

304 dtype: datetime64[us] 

305 >>> hours_series.dt.hour 

306 0 0 

307 1 1 

308 2 2 

309 dtype: int32 

310 

311 >>> quarters_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="QE")) 

312 >>> quarters_series 

313 0 2000-03-31 

314 1 2000-06-30 

315 2 2000-09-30 

316 dtype: datetime64[us] 

317 >>> quarters_series.dt.quarter 

318 0 1 

319 1 2 

320 2 3 

321 dtype: int32 

322 

323 Returns a Series indexed like the original Series. 

324 Raises TypeError if the Series does not contain datetimelike values. 

325 """ 

326 

327 def to_pydatetime(self) -> Series: 

328 """ 

329 Return the data as a Series of :class:`datetime.datetime` objects. 

330 

331 Timezone information is retained if present. 

332 

333 .. warning:: 

334 

335 Python's datetime uses microsecond resolution, which is lower than 

336 pandas (nanosecond). The values are truncated. 

337 

338 Returns 

339 ------- 

340 Series 

341 Series containing native Python datetime objects. 

342 

343 See Also 

344 -------- 

345 datetime.datetime : Standard library value for a datetime. 

346 

347 Examples 

348 -------- 

349 >>> s = pd.Series(pd.date_range("20180310", periods=2)) 

350 >>> s 

351 0 2018-03-10 

352 1 2018-03-11 

353 dtype: datetime64[us] 

354 

355 >>> s.dt.to_pydatetime() 

356 0 2018-03-10 00:00:00 

357 1 2018-03-11 00:00:00 

358 dtype: object 

359 

360 pandas' nanosecond precision is truncated to microseconds. 

361 

362 >>> s = pd.Series(pd.date_range("20180310", periods=2, freq="ns")) 

363 >>> s 

364 0 2018-03-10 00:00:00.000000000 

365 1 2018-03-10 00:00:00.000000001 

366 dtype: datetime64[ns] 

367 

368 >>> s.dt.to_pydatetime() 

369 0 2018-03-10 00:00:00 

370 1 2018-03-10 00:00:00 

371 dtype: object 

372 """ 

373 # GH#20306 

374 from pandas import Series 

375 

376 return Series( 

377 self._get_values().to_pydatetime(), 

378 index=self._parent.index, 

379 name=self._parent.name, 

380 dtype=object, 

381 ) 

382 

383 @property 

384 def freq(self): 

385 """ 

386 Return a string representing a frequency generated by infer_freq. 

387 

388 .. deprecated:: 3.1.0 

389 A future version of pandas will return a :class:`BaseOffset` 

390 object (or ``None``) instead of a string. Use 

391 ``pd.set_option('future.infer_freq_returns_offset', True)`` to 

392 opt in to the future behavior. 

393 

394 Returns None if it can't autodetect the frequency. 

395 

396 See Also 

397 -------- 

398 Series.dt.to_period : Cast to PeriodArray/PeriodIndex at a particular 

399 frequency. 

400 

401 Examples 

402 -------- 

403 >>> ser = pd.Series(["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04"]) 

404 >>> ser = pd.to_datetime(ser) 

405 >>> ser.dt.freq 

406 'D' 

407 

408 >>> ser = pd.Series(["2022-01-01", "2024-01-01", "2026-01-01", "2028-01-01"]) 

409 >>> ser = pd.to_datetime(ser) 

410 >>> ser.dt.freq 

411 '2YS-JAN' 

412 """ 

413 return frequencies.maybe_convert_inferred_freq( 

414 self._get_values()._inferred_freq_str, "Series.dt.freq" 

415 ) 

416 

417 def isocalendar(self) -> DataFrame: 

418 """ 

419 Calculate year, week, and day according to the ISO 8601 standard. 

420 

421 The ISO 8601 standard defines the first week of the year as the week 

422 containing the first Thursday. This method returns a DataFrame with 

423 columns for the ISO year, ISO week number, and ISO day of week. 

424 

425 Returns 

426 ------- 

427 DataFrame 

428 With columns year, week and day. 

429 

430 See Also 

431 -------- 

432 Timestamp.isocalendar : Function return a 3-tuple containing ISO year, 

433 week number, and weekday for the given Timestamp object. 

434 datetime.date.isocalendar : Return a named tuple object with 

435 three components: year, week and weekday. 

436 

437 Examples 

438 -------- 

439 >>> ser = pd.to_datetime(pd.Series(["2010-01-01", pd.NaT])) 

440 >>> ser.dt.isocalendar() 

441 year week day 

442 0 2009 53 5 

443 1 <NA> <NA> <NA> 

444 >>> ser.dt.isocalendar().week 

445 0 53 

446 1 <NA> 

447 Name: week, dtype: UInt32 

448 """ 

449 return self._get_values().isocalendar().set_index(self._parent.index) 

450 

451 @property 

452 def weekday(self) -> Series: 

453 """ 

454 The day of the week with Monday=0, Sunday=6. 

455 

456 .. deprecated:: 3.1.0 

457 Use :attr:`Series.dt.day_of_week` instead. 

458 """ 

459 warnings.warn( 

460 "Series.dt.weekday is deprecated and will be removed " 

461 "in a future version. Use Series.dt.day_of_week instead.", 

462 Pandas4Warning, 

463 stacklevel=find_stack_level(), 

464 ) 

465 return self.day_of_week # type: ignore[attr-defined] 

466 

467 @property 

468 def dayofweek(self) -> Series: 

469 """ 

470 The day of the week with Monday=0, Sunday=6. 

471 

472 .. deprecated:: 3.1.0 

473 Use :attr:`Series.dt.day_of_week` instead. 

474 """ 

475 warnings.warn( 

476 "Series.dt.dayofweek is deprecated and will be removed in a " 

477 "future version. Use Series.dt.day_of_week instead.", 

478 Pandas4Warning, 

479 stacklevel=find_stack_level(), 

480 ) 

481 return self.day_of_week # type: ignore[attr-defined] 

482 

483 @property 

484 def dayofyear(self) -> Series: 

485 """ 

486 The ordinal day of the year. 

487 

488 .. deprecated:: 3.1.0 

489 Use :attr:`Series.dt.day_of_year` instead. 

490 """ 

491 warnings.warn( 

492 "Series.dt.dayofyear is deprecated and will be removed in a " 

493 "future version. Use Series.dt.day_of_year instead.", 

494 Pandas4Warning, 

495 stacklevel=find_stack_level(), 

496 ) 

497 return self.day_of_year # type: ignore[attr-defined] 

498 

499 @property 

500 def daysinmonth(self) -> Series: 

501 """ 

502 The number of days in the month. 

503 

504 .. deprecated:: 3.1.0 

505 Use :attr:`Series.dt.days_in_month` instead. 

506 """ 

507 warnings.warn( 

508 "Series.dt.daysinmonth is deprecated and will be removed in a " 

509 "future version. Use Series.dt.days_in_month instead.", 

510 Pandas4Warning, 

511 stacklevel=find_stack_level(), 

512 ) 

513 return self.days_in_month # type: ignore[attr-defined] 

514 

515 

516@delegate_names( 

517 delegate=TimedeltaArray, accessors=TimedeltaArray._datetimelike_ops, typ="property" 

518) 

519@delegate_names( 

520 delegate=TimedeltaArray, 

521 accessors=TimedeltaArray._datetimelike_methods, 

522 typ="method", 

523) 

524class TimedeltaProperties(Properties): 

525 """ 

526 Accessor object for datetimelike properties of the Series values. 

527 

528 Returns a Series indexed like the original Series. 

529 Raises TypeError if the Series does not contain datetimelike values. 

530 

531 Examples 

532 -------- 

533 >>> seconds_series = pd.Series( 

534 ... pd.timedelta_range(start="1 second", periods=3, freq="s") 

535 ... ) 

536 >>> seconds_series 

537 0 0 days 00:00:01 

538 1 0 days 00:00:02 

539 2 0 days 00:00:03 

540 dtype: timedelta64[us] 

541 >>> seconds_series.dt.seconds 

542 0 1 

543 1 2 

544 2 3 

545 dtype: int32 

546 """ 

547 

548 def to_pytimedelta(self) -> np.ndarray: 

549 """ 

550 Return an array of native :class:`datetime.timedelta` objects. 

551 

552 Python's standard `datetime` library uses a different representation 

553 timedelta's. This method converts a Series of pandas Timedeltas 

554 to `datetime.timedelta` format with the same length as the original 

555 Series. 

556 

557 Returns 

558 ------- 

559 numpy.ndarray 

560 Array of 1D containing data with `datetime.timedelta` type. 

561 

562 See Also 

563 -------- 

564 datetime.timedelta : A duration expressing the difference 

565 between two date, time, or datetime. 

566 

567 Examples 

568 -------- 

569 >>> s = pd.Series(pd.to_timedelta(np.arange(5), unit="D")) 

570 >>> s 

571 0 0 days 

572 1 1 days 

573 2 2 days 

574 3 3 days 

575 4 4 days 

576 dtype: timedelta64[us] 

577 

578 >>> s.dt.to_pytimedelta() 

579 array([datetime.timedelta(0), datetime.timedelta(days=1), 

580 datetime.timedelta(days=2), datetime.timedelta(days=3), 

581 datetime.timedelta(days=4)], dtype=object) 

582 """ 

583 # GH 57463 

584 warnings.warn( 

585 f"The behavior of {type(self).__name__}.to_pytimedelta is deprecated, " 

586 "in a future version this will return a Series containing python " 

587 "datetime.timedelta objects instead of an ndarray. To retain the " 

588 "old behavior, call `np.array` on the result", 

589 Pandas4Warning, 

590 stacklevel=find_stack_level(), 

591 ) 

592 return self._get_values().to_pytimedelta() 

593 

594 @property 

595 def components(self) -> DataFrame: 

596 """ 

597 Return a Dataframe of the components of the Timedeltas. 

598 

599 Each row of the DataFrame corresponds to a Timedelta in the original 

600 Series and contains the individual components (days, hours, minutes, 

601 seconds, milliseconds, microseconds, nanoseconds) of the Timedelta. 

602 

603 Returns 

604 ------- 

605 DataFrame 

606 

607 See Also 

608 -------- 

609 TimedeltaIndex.components : Return a DataFrame of the individual resolution 

610 components of the Timedeltas. 

611 Series.dt.total_seconds : Return the total number of seconds in the duration. 

612 

613 Examples 

614 -------- 

615 >>> s = pd.Series(pd.to_timedelta(np.arange(5), unit="s")) 

616 >>> s 

617 0 0 days 00:00:00 

618 1 0 days 00:00:01 

619 2 0 days 00:00:02 

620 3 0 days 00:00:03 

621 4 0 days 00:00:04 

622 dtype: timedelta64[us] 

623 >>> s.dt.components 

624 days hours minutes seconds milliseconds microseconds nanoseconds 

625 0 0 0 0 0 0 0 0 

626 1 0 0 0 1 0 0 0 

627 2 0 0 0 2 0 0 0 

628 3 0 0 0 3 0 0 0 

629 4 0 0 0 4 0 0 0 

630 """ 

631 return ( 

632 self._get_values() 

633 .components.set_index(self._parent.index) 

634 .__finalize__(self._parent) 

635 ) 

636 

637 @property 

638 def freq(self): 

639 """ 

640 Return a string representing a frequency generated by infer_freq. 

641 

642 .. deprecated:: 3.1.0 

643 A future version of pandas will return a :class:`BaseOffset` 

644 object (or ``None``) instead of a string. Use 

645 ``pd.set_option('future.infer_freq_returns_offset', True)`` to 

646 opt in to the future behavior. 

647 

648 Returns None if it can't autodetect the frequency. 

649 

650 See Also 

651 -------- 

652 Series.dt.components : Return a DataFrame of the components of the 

653 Timedeltas. 

654 

655 Examples 

656 -------- 

657 >>> ser = pd.Series(pd.timedelta_range("1 day", periods=4)) 

658 >>> ser.dt.freq 

659 'D' 

660 

661 >>> ser = pd.Series(pd.to_timedelta(["1 day", "3 days", "10 days"])) 

662 >>> ser.dt.freq is None 

663 True 

664 """ 

665 return frequencies.maybe_convert_inferred_freq( 

666 self._get_values()._inferred_freq_str, "Series.dt.freq" 

667 ) 

668 

669 

670@delegate_names( 

671 delegate=PeriodArray, accessors=PeriodArray._datetimelike_ops, typ="property" 

672) 

673@delegate_names( 

674 delegate=PeriodArray, accessors=PeriodArray._datetimelike_methods, typ="method" 

675) 

676class PeriodProperties(Properties): 

677 """ 

678 Accessor object for datetimelike properties of the Series values. 

679 

680 Returns a Series indexed like the original Series. 

681 Raises TypeError if the Series does not contain datetimelike values. 

682 

683 Examples 

684 -------- 

685 >>> seconds_series = pd.Series( 

686 ... pd.period_range( 

687 ... start="2000-01-01 00:00:00", end="2000-01-01 00:00:03", freq="s" 

688 ... ) 

689 ... ) 

690 >>> seconds_series 

691 0 2000-01-01 00:00:00 

692 1 2000-01-01 00:00:01 

693 2 2000-01-01 00:00:02 

694 3 2000-01-01 00:00:03 

695 dtype: period[s] 

696 >>> seconds_series.dt.second 

697 0 0 

698 1 1 

699 2 2 

700 3 3 

701 dtype: int64 

702 

703 >>> hours_series = pd.Series( 

704 ... pd.period_range(start="2000-01-01 00:00", end="2000-01-01 03:00", freq="h") 

705 ... ) 

706 >>> hours_series 

707 0 2000-01-01 00:00 

708 1 2000-01-01 01:00 

709 2 2000-01-01 02:00 

710 3 2000-01-01 03:00 

711 dtype: period[h] 

712 >>> hours_series.dt.hour 

713 0 0 

714 1 1 

715 2 2 

716 3 3 

717 dtype: int64 

718 

719 >>> quarters_series = pd.Series( 

720 ... pd.period_range(start="2000-01-01", end="2000-12-31", freq="Q-DEC") 

721 ... ) 

722 >>> quarters_series 

723 0 2000Q1 

724 1 2000Q2 

725 2 2000Q3 

726 3 2000Q4 

727 dtype: period[Q-DEC] 

728 >>> quarters_series.dt.quarter 

729 0 1 

730 1 2 

731 2 3 

732 3 4 

733 dtype: int64 

734 """ 

735 

736 @property 

737 def weekday(self) -> Series: 

738 """ 

739 The day of the week with Monday=0, Sunday=6. 

740 

741 .. deprecated:: 3.1.0 

742 Use :attr:`Series.dt.day_of_week` instead. 

743 """ 

744 warnings.warn( 

745 "Series.dt.weekday is deprecated and will be removed " 

746 "in a future version. Use Series.dt.day_of_week instead.", 

747 Pandas4Warning, 

748 stacklevel=find_stack_level(), 

749 ) 

750 return self.day_of_week # type: ignore[attr-defined] 

751 

752 @property 

753 def dayofweek(self): 

754 """ 

755 The day of the week with Monday=0, Sunday=6. 

756 

757 .. deprecated:: 3.1.0 

758 Use :attr:`Series.dt.day_of_week` instead. 

759 """ 

760 warnings.warn( 

761 "Series.dt.dayofweek is deprecated and will be removed in a " 

762 "future version. Use Series.dt.day_of_week instead.", 

763 Pandas4Warning, 

764 stacklevel=find_stack_level(), 

765 ) 

766 return self.day_of_week # type: ignore[attr-defined] 

767 

768 @property 

769 def dayofyear(self): 

770 """ 

771 The ordinal day of the year. 

772 

773 .. deprecated:: 3.1.0 

774 Use :attr:`Series.dt.day_of_year` instead. 

775 """ 

776 warnings.warn( 

777 "Series.dt.dayofyear is deprecated and will be removed in a " 

778 "future version. Use Series.dt.day_of_year instead.", 

779 Pandas4Warning, 

780 stacklevel=find_stack_level(), 

781 ) 

782 return self.day_of_year # type: ignore[attr-defined] 

783 

784 @property 

785 def daysinmonth(self): 

786 """ 

787 The number of days in the month. 

788 

789 .. deprecated:: 3.1.0 

790 Use :attr:`Series.dt.days_in_month` instead. 

791 """ 

792 warnings.warn( 

793 "Series.dt.daysinmonth is deprecated and will be removed in a " 

794 "future version. Use Series.dt.days_in_month instead.", 

795 Pandas4Warning, 

796 stacklevel=find_stack_level(), 

797 ) 

798 return self.days_in_month # type: ignore[attr-defined] 

799 

800 

801class CombinedDatetimelikeProperties( 

802 DatetimeProperties, TimedeltaProperties, PeriodProperties 

803): 

804 """ 

805 Accessor object for Series values' datetime-like, timedelta and period properties. 

806 

807 This accessor provides access to properties and methods for datetime-like, 

808 timedelta, and period data types. It can be used with Series containing 

809 datetime64, timedelta64, or period data. 

810 

811 Parameters 

812 ---------- 

813 data : Series 

814 Series with datetime-like, timedelta, or period dtype. 

815 

816 See Also 

817 -------- 

818 DatetimeIndex : Index of datetime64 data. 

819 

820 Examples 

821 -------- 

822 >>> dates = pd.Series( 

823 ... ["2024-01-01", "2024-01-15", "2024-02-5"], dtype="datetime64[ns]" 

824 ... ) 

825 >>> dates.dt.day 

826 0 1 

827 1 15 

828 2 5 

829 dtype: int32 

830 >>> dates.dt.month 

831 0 1 

832 1 1 

833 2 2 

834 dtype: int32 

835 

836 >>> dates = pd.Series( 

837 ... ["2024-01-01", "2024-01-15", "2024-02-5"], dtype="datetime64[ns, UTC]" 

838 ... ) 

839 >>> dates.dt.day 

840 0 1 

841 1 15 

842 2 5 

843 dtype: int32 

844 >>> dates.dt.month 

845 0 1 

846 1 1 

847 2 2 

848 dtype: int32 

849 """ 

850 

851 def __new__(cls, data: Series): # pyright: ignore[reportInconsistentConstructor] 

852 # CombinedDatetimelikeProperties isn't really instantiated. Instead 

853 # we need to choose which parent (datetime or timedelta) is 

854 # appropriate. Since we're checking the dtypes anyway, we'll just 

855 # do all the validation here. 

856 

857 if not isinstance(data, ABCSeries): 

858 raise TypeError( 

859 f"cannot convert an object of type {type(data)} to a datetimelike index" 

860 ) 

861 

862 orig = data if isinstance(data.dtype, CategoricalDtype) else None 

863 if orig is not None: 

864 data = data._constructor( 

865 orig.array, 

866 name=orig.name, 

867 copy=False, 

868 dtype=orig._values.categories.dtype, 

869 index=orig.index, 

870 ) 

871 

872 if isinstance(data.dtype, ArrowDtype) and data.dtype.kind in "Mm": 

873 return ArrowTemporalProperties(data, orig) 

874 if lib.is_np_dtype(data.dtype, "M"): 

875 return DatetimeProperties(data, orig) 

876 elif isinstance(data.dtype, DatetimeTZDtype): 

877 return DatetimeProperties(data, orig) 

878 elif lib.is_np_dtype(data.dtype, "m"): 

879 return TimedeltaProperties(data, orig) 

880 elif isinstance(data.dtype, PeriodDtype): 

881 return PeriodProperties(data, orig) 

882 

883 raise AttributeError("Can only use .dt accessor with datetimelike values")