@@ -123,7 +123,7 @@ cdef inline object create_timestamp_from_ts(int64_t value,
123
123
dts.day, dts.hour, dts.min,
124
124
dts.sec, dts.us, tz, fold = fold)
125
125
ts_base.value = value
126
- ts_base.freq = freq
126
+ ts_base._freq = freq
127
127
ts_base.nanosecond = dts.ps // 1000
128
128
129
129
return ts_base
@@ -155,6 +155,21 @@ cdef class _Timestamp(ABCTimestamp):
155
155
dayofweek = _Timestamp.day_of_week
156
156
dayofyear = _Timestamp.day_of_year
157
157
158
+ cpdef void _set_freq(self , freq):
159
+ # set the ._freq attribute without going through the constructor,
160
+ # which would issue a warning
161
+ # Caller is responsible for validation
162
+ self ._freq = freq
163
+
164
+ @property
165
+ def freq (self ):
166
+ warnings.warn(
167
+ " Timestamp.freq is deprecated and will be removed in a future version" ,
168
+ FutureWarning ,
169
+ stacklevel = 1 ,
170
+ )
171
+ return self ._freq
172
+
158
173
def __hash__ (_Timestamp self ):
159
174
if self .nanosecond:
160
175
return hash (self .value)
@@ -263,7 +278,9 @@ cdef class _Timestamp(ABCTimestamp):
263
278
264
279
if is_any_td_scalar(other):
265
280
nanos = delta_to_nanoseconds(other)
266
- result = type (self )(self .value + nanos, tz = self .tzinfo, freq = self .freq)
281
+ result = type (self )(self .value + nanos, tz = self .tzinfo)
282
+ if result is not NaT:
283
+ result._set_freq(self ._freq) # avoid warning in constructor
267
284
return result
268
285
269
286
elif is_integer_object(other):
@@ -361,18 +378,17 @@ cdef class _Timestamp(ABCTimestamp):
361
378
val = self .value
362
379
return val
363
380
364
- cdef bint _get_start_end_field(self , str field):
381
+ cdef bint _get_start_end_field(self , str field, freq ):
365
382
cdef:
366
383
int64_t val
367
384
dict kwds
368
385
ndarray[uint8_t, cast= True ] out
369
386
int month_kw
370
387
371
- freq = self .freq
372
388
if freq:
373
389
kwds = freq.kwds
374
390
month_kw = kwds.get(' startingMonth' , kwds.get(' month' , 12 ))
375
- freqstr = self .freqstr
391
+ freqstr = self ._freqstr
376
392
else :
377
393
month_kw = 12
378
394
freqstr = None
@@ -382,6 +398,31 @@ cdef class _Timestamp(ABCTimestamp):
382
398
field, freqstr, month_kw)
383
399
return out[0 ]
384
400
401
+ cdef _warn_on_field_deprecation(self , freq, str field):
402
+ """
403
+ Warn if the removal of .freq change the value of start/end properties.
404
+ """
405
+ cdef:
406
+ bint needs = False
407
+
408
+ if freq is not None :
409
+ kwds = freq.kwds
410
+ month_kw = kwds.get(" startingMonth" , kwds.get(" month" , 12 ))
411
+ freqstr = self ._freqstr
412
+ if month_kw != 12 :
413
+ needs = True
414
+ if freqstr.startswith(" B" ):
415
+ needs = True
416
+
417
+ if needs:
418
+ warnings.warn(
419
+ " Timestamp.freq is deprecated and will be removed in a future "
420
+ " version. When you have a freq, use "
421
+ f" freq.{field}(timestamp) instead" ,
422
+ FutureWarning ,
423
+ stacklevel = 1 ,
424
+ )
425
+
385
426
@property
386
427
def is_month_start (self ) -> bool:
387
428
"""
@@ -397,10 +438,11 @@ cdef class _Timestamp(ABCTimestamp):
397
438
>>> ts.is_month_start
398
439
True
399
440
"""
400
- if self.freq is None:
441
+ if self._freq is None:
401
442
# fast-path for non-business frequencies
402
443
return self.day == 1
403
- return self._get_start_end_field("is_month_start")
444
+ self._warn_on_field_deprecation(self._freq , "is_month_start")
445
+ return self._get_start_end_field("is_month_start", self._freq )
404
446
405
447
@property
406
448
def is_month_end(self ) -> bool:
@@ -417,10 +459,11 @@ cdef class _Timestamp(ABCTimestamp):
417
459
>>> ts.is_month_end
418
460
True
419
461
"""
420
- if self.freq is None:
462
+ if self._freq is None:
421
463
# fast-path for non-business frequencies
422
464
return self.day == self.days_in_month
423
- return self._get_start_end_field("is_month_end")
465
+ self._warn_on_field_deprecation(self._freq , "is_month_end")
466
+ return self._get_start_end_field("is_month_end", self._freq )
424
467
425
468
@property
426
469
def is_quarter_start(self ) -> bool:
@@ -437,10 +480,11 @@ cdef class _Timestamp(ABCTimestamp):
437
480
>>> ts.is_quarter_start
438
481
True
439
482
"""
440
- if self.freq is None:
483
+ if self._freq is None:
441
484
# fast-path for non-business frequencies
442
485
return self.day == 1 and self.month % 3 == 1
443
- return self._get_start_end_field("is_quarter_start")
486
+ self._warn_on_field_deprecation(self._freq , "is_quarter_start")
487
+ return self._get_start_end_field("is_quarter_start", self._freq )
444
488
445
489
@property
446
490
def is_quarter_end(self ) -> bool:
@@ -457,10 +501,11 @@ cdef class _Timestamp(ABCTimestamp):
457
501
>>> ts.is_quarter_end
458
502
True
459
503
"""
460
- if self.freq is None:
504
+ if self._freq is None:
461
505
# fast-path for non-business frequencies
462
506
return (self.month % 3) == 0 and self.day == self.days_in_month
463
- return self._get_start_end_field("is_quarter_end")
507
+ self._warn_on_field_deprecation(self._freq , "is_quarter_end")
508
+ return self._get_start_end_field("is_quarter_end", self._freq )
464
509
465
510
@property
466
511
def is_year_start(self ) -> bool:
@@ -477,10 +522,11 @@ cdef class _Timestamp(ABCTimestamp):
477
522
>>> ts.is_year_start
478
523
True
479
524
"""
480
- if self.freq is None:
525
+ if self._freq is None:
481
526
# fast-path for non-business frequencies
482
527
return self.day == self.month == 1
483
- return self._get_start_end_field("is_year_start")
528
+ self._warn_on_field_deprecation(self._freq , "is_year_start")
529
+ return self._get_start_end_field("is_year_start", self._freq )
484
530
485
531
@property
486
532
def is_year_end(self ) -> bool:
@@ -497,10 +543,11 @@ cdef class _Timestamp(ABCTimestamp):
497
543
>>> ts.is_year_end
498
544
True
499
545
"""
500
- if self.freq is None:
546
+ if self._freq is None:
501
547
# fast-path for non-business frequencies
502
548
return self.month == 12 and self.day == 31
503
- return self._get_start_end_field("is_year_end")
549
+ self._warn_on_field_deprecation(self._freq , "is_year_end")
550
+ return self._get_start_end_field("is_year_end", self._freq )
504
551
505
552
cdef _get_date_name_field(self , str field , object locale ):
506
553
cdef:
@@ -673,11 +720,11 @@ cdef class _Timestamp(ABCTimestamp):
673
720
674
721
def __setstate__ (self , state ):
675
722
self .value = state[0 ]
676
- self .freq = state[1 ]
723
+ self ._freq = state[1 ]
677
724
self .tzinfo = state[2 ]
678
725
679
726
def __reduce__ (self ):
680
- object_state = self .value, self .freq , self .tzinfo
727
+ object_state = self .value, self ._freq , self .tzinfo
681
728
return (Timestamp, object_state)
682
729
683
730
# -----------------------------------------------------------------
@@ -719,7 +766,7 @@ cdef class _Timestamp(ABCTimestamp):
719
766
pass
720
767
721
768
tz = f" , tz='{zone}'" if zone is not None else " "
722
- freq = " " if self .freq is None else f" , freq='{self.freqstr }'"
769
+ freq = " " if self ._freq is None else f" , freq='{self._freqstr }'"
723
770
724
771
return f"Timestamp('{stamp}'{tz}{freq})"
725
772
@@ -877,7 +924,13 @@ cdef class _Timestamp(ABCTimestamp):
877
924
)
878
925
879
926
if freq is None :
880
- freq = self .freq
927
+ freq = self ._freq
928
+ warnings.warn(
929
+ " In a future version, calling 'Timestamp.to_period()' without "
930
+ " passing a 'freq' will raise an exception." ,
931
+ FutureWarning ,
932
+ stacklevel = 2 ,
933
+ )
881
934
882
935
return Period(self , freq = freq)
883
936
@@ -1147,7 +1200,7 @@ class Timestamp(_Timestamp):
1147
1200
nanosecond = None ,
1148
1201
tzinfo_type tzinfo = None ,
1149
1202
*,
1150
- fold = None
1203
+ fold = None ,
1151
1204
):
1152
1205
# The parameter list folds together legacy parameter names (the first
1153
1206
# four) and positional and keyword parameter names from pydatetime.
@@ -1276,9 +1329,16 @@ class Timestamp(_Timestamp):
1276
1329
1277
1330
if freq is None :
1278
1331
# GH 22311: Try to extract the frequency of a given Timestamp input
1279
- freq = getattr (ts_input, ' freq' , None )
1280
- elif not is_offset_object(freq):
1281
- freq = to_offset(freq)
1332
+ freq = getattr (ts_input, ' _freq' , None )
1333
+ else :
1334
+ warnings.warn(
1335
+ " The 'freq' argument in Timestamp is deprecated and will be "
1336
+ " removed in a future version." ,
1337
+ FutureWarning ,
1338
+ stacklevel = 1 ,
1339
+ )
1340
+ if not is_offset_object(freq):
1341
+ freq = to_offset(freq)
1282
1342
1283
1343
return create_timestamp_from_ts(ts.value, ts.dts, ts.tzinfo, freq, ts.fold)
1284
1344
@@ -1551,12 +1611,21 @@ timedelta}, default 'raise'
1551
1611
" Use tz_localize() or tz_convert() as appropriate"
1552
1612
)
1553
1613
1614
+ @property
1615
+ def _freqstr (self ):
1616
+ return getattr (self ._freq, " freqstr" , self ._freq)
1617
+
1554
1618
@property
1555
1619
def freqstr (self ):
1556
1620
"""
1557
1621
Return the total number of days in the month.
1558
1622
"""
1559
- return getattr (self .freq, ' freqstr' , self .freq)
1623
+ warnings.warn(
1624
+ " Timestamp.freqstr is deprecated and will be removed in a future version." ,
1625
+ FutureWarning ,
1626
+ stacklevel = 1 ,
1627
+ )
1628
+ return self ._freqstr
1560
1629
1561
1630
def tz_localize (self , tz , ambiguous = ' raise' , nonexistent = ' raise' ):
1562
1631
"""
@@ -1647,12 +1716,18 @@ default 'raise'
1647
1716
value = tz_localize_to_utc_single(self .value, tz,
1648
1717
ambiguous = ambiguous,
1649
1718
nonexistent = nonexistent)
1650
- return Timestamp(value, tz = tz, freq = self .freq)
1719
+ out = Timestamp(value, tz = tz)
1720
+ if out is not NaT:
1721
+ out._set_freq(self ._freq) # avoid warning in constructor
1722
+ return out
1651
1723
else :
1652
1724
if tz is None :
1653
1725
# reset tz
1654
1726
value = tz_convert_from_utc_single(self .value, self .tz)
1655
- return Timestamp(value, tz = tz, freq = self .freq)
1727
+ out = Timestamp(value, tz = tz)
1728
+ if out is not NaT:
1729
+ out._set_freq(self ._freq) # avoid warning in constructor
1730
+ return out
1656
1731
else :
1657
1732
raise TypeError (
1658
1733
" Cannot localize tz-aware Timestamp, use tz_convert for conversions"
@@ -1707,7 +1782,10 @@ default 'raise'
1707
1782
)
1708
1783
else :
1709
1784
# Same UTC timestamp, different time zone
1710
- return Timestamp(self .value, tz = tz, freq = self .freq)
1785
+ out = Timestamp(self .value, tz = tz)
1786
+ if out is not NaT:
1787
+ out._set_freq(self ._freq) # avoid warning in constructor
1788
+ return out
1711
1789
1712
1790
astimezone = tz_convert
1713
1791
@@ -1840,7 +1918,7 @@ default 'raise'
1840
1918
if value != NPY_NAT:
1841
1919
check_dts_bounds(& dts)
1842
1920
1843
- return create_timestamp_from_ts(value, dts, tzobj, self .freq , fold)
1921
+ return create_timestamp_from_ts(value, dts, tzobj, self ._freq , fold)
1844
1922
1845
1923
def to_julian_date (self ) -> np.float64:
1846
1924
"""
0 commit comments