Skip to content

Commit deca954

Browse files
authored
DEPR: make to_datetime('now') match Timestamp('now') (#45104)
1 parent 1fcccda commit deca954

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ Other Deprecations
640640
- Deprecated passing non boolean argument to sort in :func:`concat` (:issue:`41518`)
641641
- Deprecated passing arguments as positional for :func:`read_fwf` other than ``filepath_or_buffer`` (:issue:`41485`):
642642
- Deprecated passing ``skipna=None`` for :meth:`DataFrame.mad` and :meth:`Series.mad`, pass ``skipna=True`` instead (:issue:`44580`)
643+
- 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` returning the local time (:issue:`18705`)
643644
- Deprecated :meth:`DateOffset.apply`, use ``offset + other`` instead (:issue:`44522`)
644645
- Deprecated parameter ``names`` in :meth:`Index.copy` (:issue:`44916`)
645646
- 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`)

pandas/_libs/tslib.pyx

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import warnings
2+
13
import cython
24

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

757759

758-
cdef inline bint _parse_today_now(str val, int64_t* iresult):
760+
cdef inline bint _parse_today_now(str val, int64_t* iresult, bint utc):
759761
# We delay this check for as long as possible
760762
# because it catches relatively rare cases
761-
if val == 'now':
762-
# Note: this is *not* the same as Timestamp('now')
763+
if val == "now":
763764
iresult[0] = Timestamp.utcnow().value
765+
if not utc:
766+
# GH#18705 make sure to_datetime("now") matches Timestamp("now")
767+
warnings.warn(
768+
"The parsing of 'now' in pd.to_datetime without `utc=True` is "
769+
"deprecated. In a future version, this will match Timestamp('now') "
770+
"and Timestamp.now()",
771+
FutureWarning,
772+
stacklevel=1,
773+
)
774+
764775
return True
765-
elif val == 'today':
776+
elif val == "today":
766777
iresult[0] = Timestamp.today().value
767778
return True
768779
return False

pandas/tests/arithmetic/test_datetime64.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1679,8 +1679,8 @@ def test_dt64_series_arith_overflow(self):
16791679
tm.assert_series_equal(res, -expected)
16801680

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

16851685
tsneg = Timestamp("1950-01-01")
16861686
ts_neg_variants = [
@@ -1718,8 +1718,8 @@ def test_datetimeindex_sub_timestamp_overflow(self):
17181718

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

17241724
ts_neg = pd.to_datetime(["1950-01-01", "1950-01-01"])
17251725
ts_pos = pd.to_datetime(["1980-01-01", "1980-01-01"])

pandas/tests/tools/test_to_datetime.py

+15-4
Original file line numberDiff line numberDiff line change
@@ -591,9 +591,15 @@ def test_to_datetime_unparseable_ignore(self):
591591
def test_to_datetime_now(self):
592592
# See GH#18666
593593
with tm.set_timezone("US/Eastern"):
594-
npnow = np.datetime64("now").astype("datetime64[ns]")
595-
pdnow = to_datetime("now")
596-
pdnow2 = to_datetime(["now"])[0]
594+
msg = "The parsing of 'now' in pd.to_datetime"
595+
with tm.assert_produces_warning(
596+
FutureWarning, match=msg, check_stacklevel=False
597+
):
598+
# checking stacklevel is tricky because we go through cython code
599+
# GH#18705
600+
npnow = np.datetime64("now").astype("datetime64[ns]")
601+
pdnow = to_datetime("now")
602+
pdnow2 = to_datetime(["now"])[0]
597603

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

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

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

0 commit comments

Comments
 (0)