.. _timedeltas: {{ header }} .. _timedeltas.timedeltas: *********** Time deltas *********** Timedeltas are differences in times, expressed in difference units, e.g. days, hours, minutes, seconds. They can be both positive and negative. ``Timedelta`` is a subclass of ``datetime.timedelta``, and behaves in a similar manner, but allows compatibility with ``np.timedelta64`` types as well as a host of custom representation, parsing, and attributes. Parsing ------- You can construct a ``Timedelta`` scalar through various arguments, including `ISO 8601 Duration`_ strings. .. ipython:: python import datetime # strings pd.Timedelta("1 days") pd.Timedelta("1 days 00:00:00") pd.Timedelta("1 days 2 hours") pd.Timedelta("-1 days 2 min 3us") # like datetime.timedelta # note: these MUST be specified as keyword arguments pd.Timedelta(days=1, seconds=1) # integers with a unit pd.Timedelta(1, unit="d") # from a datetime.timedelta/np.timedelta64 pd.Timedelta(datetime.timedelta(days=1, seconds=1)) pd.Timedelta(np.timedelta64(1, "ms")) # negative Timedeltas have this string repr # to be more consistent with datetime.timedelta conventions pd.Timedelta("-1us") # a NaT pd.Timedelta("nan") pd.Timedelta("nat") # ISO 8601 Duration strings pd.Timedelta("P0DT0H1M0S") pd.Timedelta("P0DT0H0M0.000000123S") :ref:`DateOffsets` (``Day, Hour, Minute, Second, Milli, Micro, Nano``) can also be used in construction. .. ipython:: python pd.Timedelta(pd.offsets.Second(2)) Further, operations among the scalars yield another scalar ``Timedelta``. .. ipython:: python pd.Timedelta(pd.offsets.Day(2)) + pd.Timedelta(pd.offsets.Second(2)) + pd.Timedelta( "00:00:00.000123" ) to_timedelta ~~~~~~~~~~~~ Using the top-level ``pd.to_timedelta``, you can convert a scalar, array, list, or Series from a recognized timedelta format / value into a ``Timedelta`` type. It will construct Series if the input is a Series, a scalar if the input is scalar-like, otherwise it will output a ``TimedeltaIndex``. You can parse a single string to a Timedelta: .. ipython:: python pd.to_timedelta("1 days 06:05:01.00003") pd.to_timedelta("15.5us") or a list/array of strings: .. ipython:: python pd.to_timedelta(["1 days 06:05:01.00003", "15.5us", "nan"]) The ``unit`` keyword argument specifies the unit of the Timedelta if the input is numeric: .. ipython:: python pd.to_timedelta(np.arange(5), unit="s") pd.to_timedelta(np.arange(5), unit="d") .. warning:: If a string or array of strings is passed as an input then the ``unit`` keyword argument will be ignored. If a string without units is passed then the default unit of nanoseconds is assumed. .. _timedeltas.limitations: Timedelta limitations ~~~~~~~~~~~~~~~~~~~~~ pandas represents ``Timedeltas`` in nanosecond resolution using 64 bit integers. As such, the 64 bit integer limits determine the ``Timedelta`` limits. .. ipython:: python pd.Timedelta.min pd.Timedelta.max .. _timedeltas.operations: Operations ---------- You can operate on Series/DataFrames and construct ``timedelta64[ns]`` Series through subtraction operations on ``datetime64[ns]`` Series, or ``Timestamps``. .. ipython:: python s = pd.Series(pd.date_range("2012-1-1", periods=3, freq="D")) td = pd.Series([pd.Timedelta(days=i) for i in range(3)]) df = pd.DataFrame({"A": s, "B": td}) df df["C"] = df["A"] + df["B"] df df.dtypes s - s.max() s - datetime.datetime(2011, 1, 1, 3, 5) s + datetime.timedelta(minutes=5) s + pd.offsets.Minute(5) s + pd.offsets.Minute(5) + pd.offsets.Milli(5) Operations with scalars from a ``timedelta64[ns]`` series: .. ipython:: python y = s - s[0] y Series of timedeltas with ``NaT`` values are supported: .. ipython:: python y = s - s.shift() y Elements can be set to ``NaT`` using ``np.nan`` analogously to datetimes: .. ipython:: python y[1] = np.nan y Operands can also appear in a reversed order (a singular object operated with a Series): .. ipython:: python s.max() - s datetime.datetime(2011, 1, 1, 3, 5) - s datetime.timedelta(minutes=5) + s ``min, max`` and the corresponding ``idxmin, idxmax`` operations are supported on frames: .. ipython:: python A = s - pd.Timestamp("20120101") - pd.Timedelta("00:05:05") B = s - pd.Series(pd.date_range("2012-1-2", periods=3, freq="D")) df = pd.DataFrame({"A": A, "B": B}) df df.min() df.min(axis=1) df.idxmin() df.idxmax() ``min, max, idxmin, idxmax`` operations are supported on Series as well. A scalar result will be a ``Timedelta``. .. ipython:: python df.min().max() df.min(axis=1).min() df.min().idxmax() df.min(axis=1).idxmin() You can fillna on timedeltas, passing a timedelta to get a particular value. .. ipython:: python y.fillna(pd.Timedelta(0)) y.fillna(pd.Timedelta(10, unit="s")) y.fillna(pd.Timedelta("-1 days, 00:00:05")) You can also negate, multiply and use ``abs`` on ``Timedeltas``: .. ipython:: python td1 = pd.Timedelta("-1 days 2 hours 3 seconds") td1 -1 * td1 -td1 abs(td1) .. _timedeltas.timedeltas_reductions: Reductions ---------- Numeric reduction operation for ``timedelta64[ns]`` will return ``Timedelta`` objects. As usual ``NaT`` are skipped during evaluation. .. ipython:: python y2 = pd.Series( pd.to_timedelta(["-1 days +00:00:05", "nat", "-1 days +00:00:05", "1 days"]) ) y2 y2.mean() y2.median() y2.quantile(0.1) y2.sum() .. _timedeltas.timedeltas_convert: Frequency conversion -------------------- Timedelta Series, ``TimedeltaIndex``, and ``Timedelta`` scalars can be converted to other 'frequencies' by dividing by another timedelta, or by astyping to a specific timedelta type. These operations yield Series and propagate ``NaT`` -> ``nan``. Note that division by the NumPy scalar is true division, while astyping is equivalent of floor division. .. ipython:: python december = pd.Series(pd.date_range("20121201", periods=4)) january = pd.Series(pd.date_range("20130101", periods=4)) td = january - december td[2] += datetime.timedelta(minutes=5, seconds=3) td[3] = np.nan td # to days td / np.timedelta64(1, "D") td.astype("timedelta64[D]") # to seconds td / np.timedelta64(1, "s") td.astype("timedelta64[s]") # to months (these are constant months) td / np.timedelta64(1, "M") Dividing or multiplying a ``timedelta64[ns]`` Series by an integer or integer Series yields another ``timedelta64[ns]`` dtypes Series. .. ipython:: python td * -1 td * pd.Series([1, 2, 3, 4]) Rounded division (floor-division) of a ``timedelta64[ns]`` Series by a scalar ``Timedelta`` gives a series of integers. .. ipython:: python td // pd.Timedelta(days=3, hours=4) pd.Timedelta(days=3, hours=4) // td .. _timedeltas.mod_divmod: The mod (%) and divmod operations are defined for ``Timedelta`` when operating with another timedelta-like or with a numeric argument. .. ipython:: python pd.Timedelta(hours=37) % datetime.timedelta(hours=2) # divmod against a timedelta-like returns a pair (int, Timedelta) divmod(datetime.timedelta(hours=2), pd.Timedelta(minutes=11)) # divmod against a numeric returns a pair (Timedelta, Timedelta) divmod(pd.Timedelta(hours=25), 86400000000000) Attributes ---------- You can access various components of the ``Timedelta`` or ``TimedeltaIndex`` directly using the attributes ``days,seconds,microseconds,nanoseconds``. These are identical to the values returned by ``datetime.timedelta``, in that, for example, the ``.seconds`` attribute represents the number of seconds >= 0 and < 1 day. These are signed according to whether the ``Timedelta`` is signed. These operations can also be directly accessed via the ``.dt`` property of the ``Series`` as well. .. note:: Note that the attributes are NOT the displayed values of the ``Timedelta``. Use ``.components`` to retrieve the displayed values. For a ``Series``: .. ipython:: python td.dt.days td.dt.seconds You can access the value of the fields for a scalar ``Timedelta`` directly. .. ipython:: python tds = pd.Timedelta("31 days 5 min 3 sec") tds.days tds.seconds (-tds).seconds You can use the ``.components`` property to access a reduced form of the timedelta. This returns a ``DataFrame`` indexed similarly to the ``Series``. These are the *displayed* values of the ``Timedelta``. .. ipython:: python td.dt.components td.dt.components.seconds .. _timedeltas.isoformat: You can convert a ``Timedelta`` to an `ISO 8601 Duration`_ string with the ``.isoformat`` method .. ipython:: python pd.Timedelta( days=6, minutes=50, seconds=3, milliseconds=10, microseconds=10, nanoseconds=12 ).isoformat() .. _ISO 8601 Duration: https://en.wikipedia.org/wiki/ISO_8601#Durations .. _timedeltas.index: TimedeltaIndex -------------- To generate an index with time delta, you can use either the :class:`TimedeltaIndex` or the :func:`timedelta_range` constructor. Using ``TimedeltaIndex`` you can pass string-like, ``Timedelta``, ``timedelta``, or ``np.timedelta64`` objects. Passing ``np.nan/pd.NaT/nat`` will represent missing values. .. ipython:: python pd.TimedeltaIndex( [ "1 days", "1 days, 00:00:05", np.timedelta64(2, "D"), datetime.timedelta(days=2, seconds=2), ] ) The string 'infer' can be passed in order to set the frequency of the index as the inferred frequency upon creation: .. ipython:: python pd.TimedeltaIndex(["0 days", "10 days", "20 days"], freq="infer") Generating ranges of time deltas ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Similar to :func:`date_range`, you can construct regular ranges of a ``TimedeltaIndex`` using :func:`timedelta_range`. The default frequency for ``timedelta_range`` is calendar day: .. ipython:: python pd.timedelta_range(start="1 days", periods=5) Various combinations of ``start``, ``end``, and ``periods`` can be used with ``timedelta_range``: .. ipython:: python pd.timedelta_range(start="1 days", end="5 days") pd.timedelta_range(end="10 days", periods=4) The ``freq`` parameter can passed a variety of :ref:`frequency aliases `: .. ipython:: python pd.timedelta_range(start="1 days", end="2 days", freq="30T") pd.timedelta_range(start="1 days", periods=5, freq="2D5H") Specifying ``start``, ``end``, and ``periods`` will generate a range of evenly spaced timedeltas from ``start`` to ``end`` inclusively, with ``periods`` number of elements in the resulting ``TimedeltaIndex``: .. ipython:: python pd.timedelta_range("0 days", "4 days", periods=5) pd.timedelta_range("0 days", "4 days", periods=10) Using the TimedeltaIndex ~~~~~~~~~~~~~~~~~~~~~~~~ Similarly to other of the datetime-like indices, ``DatetimeIndex`` and ``PeriodIndex``, you can use ``TimedeltaIndex`` as the index of pandas objects. .. ipython:: python s = pd.Series( np.arange(100), index=pd.timedelta_range("1 days", periods=100, freq="h"), ) s Selections work similarly, with coercion on string-likes and slices: .. ipython:: python s["1 day":"2 day"] s["1 day 01:00:00"] s[pd.Timedelta("1 day 1h")] Furthermore you can use partial string selection and the range will be inferred: .. ipython:: python s["1 day":"1 day 5 hours"] Operations ~~~~~~~~~~ Finally, the combination of ``TimedeltaIndex`` with ``DatetimeIndex`` allow certain combination operations that are NaT preserving: .. ipython:: python tdi = pd.TimedeltaIndex(["1 days", pd.NaT, "2 days"]) tdi.to_list() dti = pd.date_range("20130101", periods=3) dti.to_list() (dti + tdi).to_list() (dti - tdi).to_list() Conversions ~~~~~~~~~~~ Similarly to frequency conversion on a ``Series`` above, you can convert these indices to yield another Index. .. ipython:: python tdi / np.timedelta64(1, "s") tdi.astype("timedelta64[s]") Scalars type ops work as well. These can potentially return a *different* type of index. .. ipython:: python # adding or timedelta and date -> datelike tdi + pd.Timestamp("20130101") # subtraction of a date and a timedelta -> datelike # note that trying to subtract a date from a Timedelta will raise an exception (pd.Timestamp("20130101") - tdi).to_list() # timedelta + timedelta -> timedelta tdi + pd.Timedelta("10 days") # division can result in a Timedelta if the divisor is an integer tdi / 2 # or a Float64Index if the divisor is a Timedelta tdi / tdi[0] .. _timedeltas.resampling: Resampling ---------- Similar to :ref:`timeseries resampling `, we can resample with a ``TimedeltaIndex``. .. ipython:: python s.resample("D").mean()