Skip to content

pandas dt.total_seconds

The one .dt method that does not work on a datetime column at all.

What it does

Have you ever tried df['when'].dt.total_seconds() and gotten an AttributeError you could not place? Here is why:

df['created_date'].dt.total_seconds()
AttributeError: 'DatetimeProperties' object has no attribute 'total_seconds'

.dt is two accessors wearing one name. On a datetime column it gives you .year, .hour, .day_name() — the parts of a moment. On a timedelta column it gives you a different set entirely, and total_seconds() is the one you reach for most. So the first step is never total_seconds. It is producing a duration, which in Pandas means subtracting one datetime column from another.

.dt.total_seconds() then turns each duration into a plain float: the whole span expressed in seconds, fractions included. It is a method, so it takes parentheses.

Official documentation: Series.dt.total_seconds and the user guide on time deltas.

A worked example, on real data

Every NYC 311 service request carries the moment it was opened and the moment it was closed, which is exactly the shape this method wants. A year of graffiti complaints is 19,201 rows:

import pandas as pd
from urllib.parse import urlencode

params = {'$select': 'created_date,closed_date,borough',
          '$where': ("complaint_type='Graffiti' and "
                     "created_date between '2025-01-01' and '2025-12-31'"),
          '$limit': 100_000}

df = pd.read_csv('https://data.cityofnewyork.us/resource/erm2-nwe9.csv?'
                 + urlencode(params),
                 parse_dates=['created_date', 'closed_date'])

delta = df['closed_date'] - df['created_date']

delta.head(3)
0   39 days 06:41:52
1   39 days 06:42:08
2    2 days 06:42:34
dtype: timedelta64[us]

That subtraction is the whole first half. The dtype is timedelta64[us], and it is already useful: delta.mean() returns 19 days 02:37:46.858286, which is a fine thing to read out loud and a terrible thing to put on an axis or into a comparison.

So convert:

(df
 .assign(days=delta.dt.total_seconds().div(86_400))
 .groupby('borough')['days'].agg(['count', 'mean', 'median']).round(1))
               count  mean  median
borough
BRONX           1858  16.5     7.5
BROOKLYN        9335  20.8    15.0
MANHATTAN       4768  16.6     6.4
QUEENS          2272  21.1    18.4
STATEN ISLAND    734  13.9     0.6
Unspecified       15   3.2     0.6

Now it is a number, so it divides, rounds, aggregates and plots. Brooklyn files half the city's graffiti complaints and takes a median of 15 days to close one; Manhattan closes half of its in under a week.

Dividing by 86,400 to get days is common enough that Pandas offers the tidier form: delta / pd.Timedelta('1D') gives the identical float, and reads better than a magic number.

Mistakes people make

Using .dt.days and thinking it is the duration. It is the whole-day part only, truncated. Its neighbor .dt.seconds is worse — it is the leftover inside that day, not the total:

pd.DataFrame({'delta': delta, 'days': delta.dt.days,
              'seconds': delta.dt.seconds,
              'total_seconds': delta.dt.total_seconds()}).head(3)
             delta  days  seconds  total_seconds
0 39 days 06:41:52  39.0  24112.0      3393712.0
1 39 days 06:42:08  39.0  24128.0      3393728.0
2  2 days 06:42:34   2.0  24154.0       196954.0

Rows 0 and 2 are 37 days apart and their seconds values differ by 42. .dt.seconds never exceeds 86,399, whatever the duration; total_seconds() is the only one of the three that answers the question. If you want the pieces laid out honestly, .dt.components gives you all seven as a data frame.

Forgetting that unfinished work is NaT. 219 of these complaints were still open, so their subtraction is NaT and their total_seconds() is NaN. mean() skips them silently, which means the average above describes closed complaints only. Say so, or count them.

Trusting a negative duration. Six rows here close before they open:

8863   -3 days +10:28:44
8864   -3 days +10:29:53

Real data does this. A quick (delta < pd.Timedelta(0)).sum() before you aggregate costs nothing and has caught more than one bad export for me.

Dropping the parentheses. total_seconds is a method. Without them you get a bound method object in the column and no error at all — the same trap as .dt.day_name, and the reason dt.year spends a paragraph on which half of the accessor needs them.

Where it shows up in Bamboo Weekly

Two Bamboo Weekly solutions use .dt.total_seconds(), and both do it for the same reason: a timedelta could not be plotted.

Bamboo Weekly #61: Solar eclipse is free to read and is the fuller example. Subtracting two columns gives the length of totality as a timedelta — Michigan's mean is 39 seconds, Illinois' is 3 minutes 16 — and then, because the map needs numbers, total_seconds() inside a case_when that assigns 0 to every location where totality was not visible at all.

Bamboo Weekly #161: Missiles in Israel builds the two datetime columns first, pairing each alert's start with its end using merge_asof with direction='forward', and only then subtracts and converts to get the length of each shelter stay.

Practice it

Work through a dt.total_seconds exercise, with instant feedback and no signup required: practice.lernerpython.com/bamboo-weekly/dt-total-seconds/

Go deeper

The datetime half of the accessor starts at dt.year and dt.hour, and none of it works until to_datetime has parsed both of your columns. Durations that arrive as text rather than as a subtraction want pd.to_timedelta. Once you have a numeric column, it is ordinary Pandas again: mean, describe and groupby. The Pandas user guide's timedelta chapter lists everything the timedelta accessor offers.

More Pandas videos on Python and Pandas with Reuven Lerner.

Bamboo Weekly is the practice. If you want the structured version — full courses with downloadable Jupyter notebooks, plus live Pandas office hours when you get stuck — that is LernerPython+Data. A paid Bamboo Weekly subscription is included with it.

See it on real data

Below are the 2 Bamboo Weekly exercises that use dt.total_seconds on real-world data — try each one, then study the worked solution.

Part of the Pandas Methods Index. See also practice by skill.