Skip to content

Commit b37321c

Browse files
authored
API: Timestamp and Timedelta .value changing in 2.0 (#50891)
* wip * wip * fixup test collection * divide by zero to debug LOL * wip * more fixups * fixup test unary ops * ewm * test offseetes * are we there yet? * _value in ujson * 🏷️ typing * wip * advise to use asm8 instead * fix test missing * make value property * un-xfail test --------- Co-authored-by: MarcoGorelli <>
1 parent 2a6d7b7 commit b37321c

Some content is hidden

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

74 files changed

+416
-353
lines changed

pandas/_libs/index.pyx

+11-7
Original file line numberDiff line numberDiff line change
@@ -517,14 +517,16 @@ cdef class DatetimeEngine(Int64Engine):
517517
# NB: caller is responsible for ensuring tzawareness compat
518518
# before we get here
519519
if scalar is NaT:
520-
return NaT.value
520+
return NaT._value
521521
elif isinstance(scalar, _Timestamp):
522522
if scalar._creso == self._creso:
523-
return scalar.value
523+
return scalar._value
524524
else:
525525
# Note: caller is responsible for catching potential ValueError
526526
# from _as_creso
527-
return (<_Timestamp>scalar)._as_creso(self._creso, round_ok=False).value
527+
return (
528+
(<_Timestamp>scalar)._as_creso(self._creso, round_ok=False)._value
529+
)
528530
raise TypeError(scalar)
529531

530532
def __contains__(self, val: object) -> bool:
@@ -585,22 +587,24 @@ cdef class TimedeltaEngine(DatetimeEngine):
585587

586588
cdef int64_t _unbox_scalar(self, scalar) except? -1:
587589
if scalar is NaT:
588-
return NaT.value
590+
return NaT._value
589591
elif isinstance(scalar, _Timedelta):
590592
if scalar._creso == self._creso:
591-
return scalar.value
593+
return scalar._value
592594
else:
593595
# Note: caller is responsible for catching potential ValueError
594596
# from _as_creso
595-
return (<_Timedelta>scalar)._as_creso(self._creso, round_ok=False).value
597+
return (
598+
(<_Timedelta>scalar)._as_creso(self._creso, round_ok=False)._value
599+
)
596600
raise TypeError(scalar)
597601

598602

599603
cdef class PeriodEngine(Int64Engine):
600604

601605
cdef int64_t _unbox_scalar(self, scalar) except? -1:
602606
if scalar is NaT:
603-
return scalar.value
607+
return scalar._value
604608
if is_period_object(scalar):
605609
# NB: we assume that we have the correct freq here.
606610
return scalar.ordinal

pandas/_libs/src/ujson/python/objToJSON.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1306,9 +1306,9 @@ char **NpyArr_encodeLabels(PyArrayObject *labels, PyObjectEncoder *enc,
13061306
castfunc(dataptr, &nanosecVal, 1, NULL, NULL);
13071307
} else if (PyDate_Check(item) || PyDelta_Check(item)) {
13081308
is_datetimelike = 1;
1309-
if (PyObject_HasAttrString(item, "value")) {
1309+
if (PyObject_HasAttrString(item, "_value")) {
13101310
// see test_date_index_and_values for case with non-nano
1311-
nanosecVal = get_long_attr(item, "value");
1311+
nanosecVal = get_long_attr(item, "_value");
13121312
} else {
13131313
if (PyDelta_Check(item)) {
13141314
nanosecVal = total_seconds(item) *
@@ -1554,8 +1554,8 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
15541554
}
15551555
return;
15561556
} else if (PyDelta_Check(obj)) {
1557-
if (PyObject_HasAttrString(obj, "value")) {
1558-
value = get_long_attr(obj, "value");
1557+
if (PyObject_HasAttrString(obj, "_value")) {
1558+
value = get_long_attr(obj, "_value");
15591559
} else {
15601560
value = total_seconds(obj) * 1000000000LL; // nanoseconds per sec
15611561
}

pandas/_libs/tslib.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ def array_to_datetime_with_tz(ndarray values, tzinfo tz):
705705
# datetime64, tznaive pydatetime, int, float
706706
ts = ts.tz_localize(tz)
707707
ts = ts.as_unit("ns")
708-
ival = ts.value
708+
ival = ts._value
709709

710710
# Analogous to: result[i] = ival
711711
(<int64_t*>cnp.PyArray_MultiIter_DATA(mi, 0))[0] = ival

pandas/_libs/tslibs/conversion.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ cdef int64_t parse_pydatetime(
765765
result = _ts.value
766766
else:
767767
if isinstance(val, _Timestamp):
768-
result = val.as_unit("ns").value
768+
result = val.as_unit("ns")._value
769769
else:
770770
result = pydatetime_to_dt64(val, dts)
771771
check_dts_bounds(dts)

pandas/_libs/tslibs/nattype.pxd

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ cdef set c_nat_strings
88

99
cdef class _NaT(datetime):
1010
cdef readonly:
11-
int64_t value
11+
int64_t _value
1212

1313
cdef _NaT c_NaT
1414

pandas/_libs/tslibs/nattype.pyi

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ class _NatComparison:
1818
def __call__(self, other: _NaTComparisonTypes) -> bool: ...
1919

2020
class NaTType:
21-
value: np.int64
21+
_value: np.int64
22+
@property
23+
def value(self) -> int: ...
2224
@property
2325
def asm8(self) -> np.datetime64: ...
2426
def to_datetime64(self) -> np.datetime64: ...

pandas/_libs/tslibs/nattype.pyx

+5-1
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,14 @@ class NaTType(_NaT):
357357
cdef _NaT base
358358

359359
base = _NaT.__new__(cls, 1, 1, 1)
360-
base.value = NPY_NAT
360+
base._value= NPY_NAT
361361

362362
return base
363363

364+
@property
365+
def value(self) -> int:
366+
return self._value
367+
364368
def __reduce_ex__(self, protocol):
365369
# python 3.6 compat
366370
# https://bugs.python.org/issue28730

pandas/_libs/tslibs/offsets.pyx

+3-3
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def apply_wraps(func):
183183
res = result.tz_localize(None)
184184
else:
185185
res = result
186-
value = res.as_unit("ns").value
186+
value = res.as_unit("ns")._value
187187
result = Timestamp(value + nano)
188188

189189
if tz is not None and result.tzinfo is None:
@@ -3530,7 +3530,7 @@ cdef class FY5253Quarter(FY5253Mixin):
35303530
else:
35313531
tdelta = Timedelta(0)
35323532

3533-
# Note: we always have tdelta.value >= 0
3533+
# Note: we always have tdelta._value>= 0
35343534
return start, num_qtrs, tdelta
35353535

35363536
@apply_wraps
@@ -3542,7 +3542,7 @@ cdef class FY5253Quarter(FY5253Mixin):
35423542
prev_year_end, num_qtrs, tdelta = self._rollback_to_year(other)
35433543
res = prev_year_end
35443544
n += num_qtrs
3545-
if self.n <= 0 and tdelta.value > 0:
3545+
if self.n <= 0 and tdelta._value > 0:
35463546
n += 1
35473547

35483548
# Possible speedup by handling years first.

pandas/_libs/tslibs/strptime.pyx

+4-4
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,14 @@ cdef bint parse_today_now(str val, int64_t* iresult, bint utc):
113113
# microsecond resolution
114114
if val == "now":
115115
if utc:
116-
iresult[0] = Timestamp.utcnow().value * 1000
116+
iresult[0] = Timestamp.utcnow()._value * 1000
117117
else:
118118
# GH#18705 make sure to_datetime("now") matches Timestamp("now")
119119
# Note using Timestamp.now() is faster than Timestamp("now")
120-
iresult[0] = Timestamp.now().value * 1000
120+
iresult[0] = Timestamp.now()._value * 1000
121121
return True
122122
elif val == "today":
123-
iresult[0] = Timestamp.today().value * 1000
123+
iresult[0] = Timestamp.today()._value * 1000
124124
return True
125125
return False
126126

@@ -284,7 +284,7 @@ def array_strptime(
284284
utc,
285285
)
286286
if isinstance(val, _Timestamp):
287-
iresult[i] = val.tz_localize(None).as_unit("ns").value
287+
iresult[i] = val.tz_localize(None).as_unit("ns")._value
288288
else:
289289
iresult[i] = pydatetime_to_dt64(val.replace(tzinfo=None), &dts)
290290
check_dts_bounds(&dts)

pandas/_libs/tslibs/timedeltas.pxd

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ cdef bint is_any_td_scalar(object obj)
1414

1515
cdef class _Timedelta(timedelta):
1616
cdef readonly:
17-
int64_t value # nanoseconds
17+
int64_t _value # nanoseconds
1818
bint _is_populated # are my components populated
1919
int64_t _d, _h, _m, _s, _ms, _us, _ns
2020
NPY_DATETIMEUNIT _creso

pandas/_libs/tslibs/timedeltas.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class Timedelta(timedelta):
8989
max: ClassVar[Timedelta]
9090
resolution: ClassVar[Timedelta]
9191
value: int # np.int64
92+
_value: int # np.int64
9293
# error: "__new__" must return a class instance (got "Union[Timestamp, NaTType]")
9394
def __new__( # type: ignore[misc]
9495
cls: type[_S],

0 commit comments

Comments
 (0)