Skip to content

DEPR: make to_datetime('now') match Timestamp('now') #45104

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 2 commits into from
Dec 31, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ Other Deprecations
- Deprecated passing non boolean argument to sort in :func:`concat` (:issue:`41518`)
- Deprecated passing arguments as positional for :func:`read_fwf` other than ``filepath_or_buffer`` (:issue:`41485`):
- Deprecated passing ``skipna=None`` for :meth:`DataFrame.mad` and :meth:`Series.mad`, pass ``skipna=True`` instead (:issue:`44580`)
- Deprecated the behavior of :func:`to_datetime` with the string "now" with ``utc=False``; in a future version this will match ``Timestamp("now")``, which in turn matches :meth:`Timestamp.now` (:issue:`18705`)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe good to mention here that Timestamp("now")/Timestamp.now returns local time.

- Deprecated :meth:`DateOffset.apply`, use ``offset + other`` instead (:issue:`44522`)
- Deprecated parameter ``names`` in :meth:`Index.copy` (:issue:`44916`)
- A deprecation warning is now shown for :meth:`DataFrame.to_latex` indicating the arguments signature may change and emulate more the arguments to :meth:`.Styler.to_latex` in future versions (:issue:`44411`)
Expand All @@ -616,7 +617,6 @@ Other Deprecations
- Deprecated ``numeric_only=None`` in :meth:`DataFrame.rank`; in a future version ``numeric_only`` must be either ``True`` or ``False`` (the default) (:issue:`45036`)
- Deprecated the behavior of :meth:`Timestamp.utcfromtimestamp`, in the future it will return a timezone-aware UTC :class:`Timestamp` (:issue:`22451`)
- Deprecated :meth:`NaT.freq` (:issue:`45071`)
-

.. ---------------------------------------------------------------------------

Expand Down
21 changes: 16 additions & 5 deletions pandas/_libs/tslib.pyx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import warnings

import cython

from cpython.datetime cimport (
Expand Down Expand Up @@ -516,7 +518,7 @@ cpdef array_to_datetime(
if string_to_dts_failed:
# An error at this point is a _parsing_ error
# specifically _not_ OutOfBoundsDatetime
if _parse_today_now(val, &iresult[i]):
if _parse_today_now(val, &iresult[i], utc):
continue
elif require_iso8601:
# if requiring iso8601 strings, skip trying
Expand Down Expand Up @@ -755,14 +757,23 @@ cdef _array_to_datetime_object(
return oresult, None


cdef inline bint _parse_today_now(str val, int64_t* iresult):
cdef inline bint _parse_today_now(str val, int64_t* iresult, bint utc):
# We delay this check for as long as possible
# because it catches relatively rare cases
if val == 'now':
# Note: this is *not* the same as Timestamp('now')
if val == "now":
iresult[0] = Timestamp.utcnow().value
if not utc:
# GH#18705 make sure to_datetime("now") matches Timestamp("now")
warnings.warn(
"The parsing of 'now' in pd.to_datetime without `utc=True` is "
"deprecated. In a future version, this will match Timestamp('now') "
"and Timestamp.now()",
FutureWarning,
stacklevel=1,
)

return True
elif val == 'today':
elif val == "today":
iresult[0] = Timestamp.today().value
return True
return False
8 changes: 4 additions & 4 deletions pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -1679,8 +1679,8 @@ def test_dt64_series_arith_overflow(self):
tm.assert_series_equal(res, -expected)

def test_datetimeindex_sub_timestamp_overflow(self):
dtimax = pd.to_datetime(["now", Timestamp.max])
dtimin = pd.to_datetime(["now", Timestamp.min])
dtimax = pd.to_datetime(["2021-12-28 17:19", Timestamp.max])
dtimin = pd.to_datetime(["2021-12-28 17:19", Timestamp.min])

tsneg = Timestamp("1950-01-01")
ts_neg_variants = [
Expand Down Expand Up @@ -1718,8 +1718,8 @@ def test_datetimeindex_sub_timestamp_overflow(self):

def test_datetimeindex_sub_datetimeindex_overflow(self):
# GH#22492, GH#22508
dtimax = pd.to_datetime(["now", Timestamp.max])
dtimin = pd.to_datetime(["now", Timestamp.min])
dtimax = pd.to_datetime(["2021-12-28 17:19", Timestamp.max])
dtimin = pd.to_datetime(["2021-12-28 17:19", Timestamp.min])

ts_neg = pd.to_datetime(["1950-01-01", "1950-01-01"])
ts_pos = pd.to_datetime(["1980-01-01", "1980-01-01"])
Expand Down
19 changes: 15 additions & 4 deletions pandas/tests/tools/test_to_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,15 @@ def test_to_datetime_unparseable_ignore(self):
def test_to_datetime_now(self):
# See GH#18666
with tm.set_timezone("US/Eastern"):
npnow = np.datetime64("now").astype("datetime64[ns]")
pdnow = to_datetime("now")
pdnow2 = to_datetime(["now"])[0]
msg = "The parsing of 'now' in pd.to_datetime"
with tm.assert_produces_warning(
FutureWarning, match=msg, check_stacklevel=False
):
# checking stacklevel is tricky because we go through cython code
# GH#18705
npnow = np.datetime64("now").astype("datetime64[ns]")
pdnow = to_datetime("now")
pdnow2 = to_datetime(["now"])[0]

# These should all be equal with infinite perf; this gives
# a generous margin of 10 seconds
Expand Down Expand Up @@ -632,7 +638,12 @@ def test_to_datetime_today(self, tz):

@pytest.mark.parametrize("arg", ["now", "today"])
def test_to_datetime_today_now_unicode_bytes(self, arg):
to_datetime([arg])
warn = FutureWarning if arg == "now" else None
msg = "The parsing of 'now' in pd.to_datetime"
with tm.assert_produces_warning(warn, match=msg, check_stacklevel=False):
# checking stacklevel is tricky because we go through cython code
# GH#18705
to_datetime([arg])

@pytest.mark.parametrize(
"dt", [np.datetime64("2000-01-01"), np.datetime64("2000-01-02")]
Expand Down