.. _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 and ``TimedeltaIndex``, and ``Timedelta`` can be converted to other frequencies by astyping to a specific timedelta dtype. .. 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 seconds td.astype("timedelta64[s]") For timedelta64 resolutions other than the supported "s", "ms", "us", "ns", an alternative is to divide by another timedelta object. Note that division by the NumPy scalar is true division, while astyping is equivalent of floor division. .. ipython:: python # to days td / np.timedelta64(1, "D") 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="30min") 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 float64 Index 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()