Skip to content

API: Timestamp and Timedelta .value changing in 2.0 #50891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions pandas/_libs/index.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -517,14 +517,16 @@ cdef class DatetimeEngine(Int64Engine):
# NB: caller is responsible for ensuring tzawareness compat
# before we get here
if scalar is NaT:
return NaT.value
return NaT._value
elif isinstance(scalar, _Timestamp):
if scalar._creso == self._creso:
return scalar.value
return scalar._value
else:
# Note: caller is responsible for catching potential ValueError
# from _as_creso
return (<_Timestamp>scalar)._as_creso(self._creso, round_ok=False).value
return (
(<_Timestamp>scalar)._as_creso(self._creso, round_ok=False)._value
)
raise TypeError(scalar)

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

cdef int64_t _unbox_scalar(self, scalar) except? -1:
if scalar is NaT:
return NaT.value
return NaT._value
elif isinstance(scalar, _Timedelta):
if scalar._creso == self._creso:
return scalar.value
return scalar._value
else:
# Note: caller is responsible for catching potential ValueError
# from _as_creso
return (<_Timedelta>scalar)._as_creso(self._creso, round_ok=False).value
return (
(<_Timedelta>scalar)._as_creso(self._creso, round_ok=False)._value
)
raise TypeError(scalar)


cdef class PeriodEngine(Int64Engine):

cdef int64_t _unbox_scalar(self, scalar) except? -1:
if scalar is NaT:
return scalar.value
return scalar._value
if is_period_object(scalar):
# NB: we assume that we have the correct freq here.
return scalar.ordinal
Expand Down
8 changes: 4 additions & 4 deletions pandas/_libs/src/ujson/python/objToJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -1306,9 +1306,9 @@ char **NpyArr_encodeLabels(PyArrayObject *labels, PyObjectEncoder *enc,
castfunc(dataptr, &nanosecVal, 1, NULL, NULL);
} else if (PyDate_Check(item) || PyDelta_Check(item)) {
is_datetimelike = 1;
if (PyObject_HasAttrString(item, "value")) {
if (PyObject_HasAttrString(item, "_value")) {
// see test_date_index_and_values for case with non-nano
nanosecVal = get_long_attr(item, "value");
nanosecVal = get_long_attr(item, "_value");
} else {
if (PyDelta_Check(item)) {
nanosecVal = total_seconds(item) *
Expand Down Expand Up @@ -1554,8 +1554,8 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
}
return;
} else if (PyDelta_Check(obj)) {
if (PyObject_HasAttrString(obj, "value")) {
value = get_long_attr(obj, "value");
if (PyObject_HasAttrString(obj, "_value")) {
value = get_long_attr(obj, "_value");
} else {
value = total_seconds(obj) * 1000000000LL; // nanoseconds per sec
}
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ def array_to_datetime_with_tz(ndarray values, tzinfo tz):
# datetime64, tznaive pydatetime, int, float
ts = ts.tz_localize(tz)
ts = ts.as_unit("ns")
ival = ts.value
ival = ts._value

# Analogous to: result[i] = ival
(<int64_t*>cnp.PyArray_MultiIter_DATA(mi, 0))[0] = ival
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/conversion.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ cdef int64_t parse_pydatetime(
result = _ts.value
else:
if isinstance(val, _Timestamp):
result = val.as_unit("ns").value
result = val.as_unit("ns")._value
else:
result = pydatetime_to_dt64(val, dts)
check_dts_bounds(dts)
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/nattype.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ cdef set c_nat_strings

cdef class _NaT(datetime):
cdef readonly:
int64_t value
int64_t _value

cdef _NaT c_NaT

Expand Down
1 change: 1 addition & 0 deletions pandas/_libs/tslibs/nattype.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class _NatComparison:

class NaTType:
value: np.int64
_value: np.int64
@property
def asm8(self) -> np.datetime64: ...
def to_datetime64(self) -> np.datetime64: ...
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/nattype.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ class NaTType(_NaT):
cdef _NaT base

base = _NaT.__new__(cls, 1, 1, 1)
base.value = NPY_NAT
base._value= NPY_NAT

return base

Expand Down
6 changes: 3 additions & 3 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def apply_wraps(func):
res = result.tz_localize(None)
else:
res = result
value = res.as_unit("ns").value
value = res.as_unit("ns")._value
result = Timestamp(value + nano)

if tz is not None and result.tzinfo is None:
Expand Down Expand Up @@ -3469,7 +3469,7 @@ cdef class FY5253Quarter(FY5253Mixin):
else:
tdelta = Timedelta(0)

# Note: we always have tdelta.value >= 0
# Note: we always have tdelta._value>= 0
return start, num_qtrs, tdelta

@apply_wraps
Expand All @@ -3481,7 +3481,7 @@ cdef class FY5253Quarter(FY5253Mixin):
prev_year_end, num_qtrs, tdelta = self._rollback_to_year(other)
res = prev_year_end
n += num_qtrs
if self.n <= 0 and tdelta.value > 0:
if self.n <= 0 and tdelta._value > 0:
n += 1

# Possible speedup by handling years first.
Expand Down
8 changes: 4 additions & 4 deletions pandas/_libs/tslibs/strptime.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ cdef bint parse_today_now(str val, int64_t* iresult, bint utc):
# microsecond resolution
if val == "now":
if utc:
iresult[0] = Timestamp.utcnow().value * 1000
iresult[0] = Timestamp.utcnow()._value * 1000
else:
# GH#18705 make sure to_datetime("now") matches Timestamp("now")
# Note using Timestamp.now() is faster than Timestamp("now")
iresult[0] = Timestamp.now().value * 1000
iresult[0] = Timestamp.now()._value * 1000
return True
elif val == "today":
iresult[0] = Timestamp.today().value * 1000
iresult[0] = Timestamp.today()._value * 1000
return True
return False

Expand Down Expand Up @@ -284,7 +284,7 @@ def array_strptime(
utc,
)
if isinstance(val, _Timestamp):
iresult[i] = val.tz_localize(None).as_unit("ns").value
iresult[i] = val.tz_localize(None).as_unit("ns")._value
else:
iresult[i] = pydatetime_to_dt64(val.replace(tzinfo=None), &dts)
check_dts_bounds(&dts)
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/timedeltas.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cdef bint is_any_td_scalar(object obj)

cdef class _Timedelta(timedelta):
cdef readonly:
int64_t value # nanoseconds
int64_t _value # nanoseconds
bint _is_populated # are my components populated
int64_t _d, _h, _m, _s, _ms, _us, _ns
NPY_DATETIMEUNIT _creso
Expand Down
1 change: 1 addition & 0 deletions pandas/_libs/tslibs/timedeltas.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class Timedelta(timedelta):
max: ClassVar[Timedelta]
resolution: ClassVar[Timedelta]
value: int # np.int64
_value: int # np.int64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be Technically Correct do we need to make value a property here?

# error: "__new__" must return a class instance (got "Union[Timestamp, NaTType]")
def __new__( # type: ignore[misc]
cls: type[_S],
Expand Down
Loading