lubridate int_length() in R: Interval Length in Seconds
The int_length() function in lubridate returns the length of an Interval object as a single numeric value in seconds. It collapses a bounded span between two timestamps to a plain number, which is the form you need for arithmetic, ratios, and comparisons against thresholds expressed in seconds, minutes, or days.
int_length(int) # length in seconds (numeric) int_length(t1 %--% t2) # works on an inline interval int_length(int) / 60 # length in minutes int_length(int) / 3600 # length in hours int_length(int) / 86400 # length in days (24h average) int_length(int_vec) # vectorised over a vector of intervals abs(int_length(int)) # ignore direction when start > end
Need explanation? Read on for examples and pitfalls.
What int_length() does in one sentence
int_length() reduces an Interval object to a single numeric value: the number of seconds between its start and its end. The result is a plain double, not a Duration object, so you can divide, compare, sum, or feed it straight into a model the same way you would any other numeric column.
The sign of the result matches the direction of the interval. A reversed interval where the end timestamp precedes the start returns a negative value, which is useful when you need to detect ordering bugs but a common source of surprise when summing lengths across a dataset.
Syntax
int_length(int) takes one argument: an Interval object or vector of Intervals. It returns a numeric vector of the same length. There are no other arguments and no options for unit conversion; the only unit is seconds.
The 30,600 figure is 8.5 hours x 3600 seconds. Because the return is plain numeric, you can divide it by 60 to get minutes or by 3600 to get hours without any class wrangling. Unit conversion happens in the calling code, not in the function.
int_length() when you need a span as a number, not as a class. If the downstream code is a comparison, an aggregation, or a column in a data frame, plain seconds are easier to handle than a Duration object. Save as.duration() for when you want lubridate to print the result with human readable units like "30600s (~8.5 hours)".Four common use cases
1. Length of a single span in minutes or hours
Divide once at the point of use. There is no need to wrap the result in as.numeric() because int_length() already returns numeric.
2. Vectorised across a column of intervals
The function vectorises naturally, so it slots into mutate() or any column expression without a loop. This is the standard pattern for converting a pair of timestamp columns into a numeric duration column.
3. Compare against a threshold
Because the result is numeric, >, <, ==, and %in% all work directly. Comparing Duration objects to numeric thresholds requires extra coercion; int_length() skips that step.
4. Aggregate lengths across rows
Summing 24.75 hours of work across three shifts is a one liner because the span is already a number. sum(as.duration(shifts)) returns a Duration object, which prints differently but holds the same value; pick the form that matches what the next step needs.
int_length() always returns seconds, regardless of how the interval was built. If the interval spans a daylight saving transition, the second count still reflects the real elapsed seconds. The calendar offset is absorbed in the start and end timestamps, not in the length.int_length() vs time_length() vs as.duration()
Three lubridate functions answer "how long is this span," and they differ in unit and return type. Picking the wrong one leads to subtle bugs around months, years, and daylight saving.
| Function | Returns | Unit | Calendar-aware? |
|---|---|---|---|
int_length(int) |
numeric | seconds | No, uses exact elapsed seconds |
time_length(int, "month") |
numeric | requested unit | Yes for "year" and "month" |
as.duration(int) |
Duration | seconds (printed with hint) | No, uses exact elapsed seconds |
as.period(int) |
Period | calendar units | Yes, "1 month" stays "1 month" |
The decision rule is simple. If you need a number in seconds, use int_length(). If you need a number in months or years that respects the calendar, use time_length(int, unit). If you need a class that prints with units, use as.duration(). If you need calendar arithmetic like "1 month later," use as.period().
The same span returns four different shapes. int_length() gives you raw seconds. time_length() gives you "1 year" because the start and end land on the same calendar date. as.duration() is the second count plus a printed hint. as.period() preserves the calendar structure.
int_length() is the gateway from class to number. Everything else in the lubridate timespan family is a class with arithmetic rules. int_length() exits that system and returns a plain double you can put in a column, a model, or a comparison.Common pitfalls
int_length() only accepts Interval objects, not Periods, Durations, or difftimes. Passing the wrong class errors out with Error: $ operator is invalid for atomic vectors or Error: int is not an Interval. Wrap a Period or Duration in interval() first, or use as.numeric() on a Duration to get seconds directly.
A reversed interval returns a negative length. If you build interval(end, start) by accident, int_length() returns a negative number rather than throwing an error. This silently corrupts sums and means until a downstream check catches it.
abs() or guard with int_flip() before aggregation. abs(int_length(int)) collapses sign issues, and int_flip(int) reorders the start and end so downstream code sees a forward facing interval. Sum totals that mix forward and reversed intervals without a guard are wrong.Try it yourself
Try it: Build an interval for a 7 hour 45 minute workday starting at 2024-04-10 09:00:00, then compute its length in minutes.
Click to reveal solution
Explanation: int_length() returns the span in seconds (27,900). Dividing by 60 converts to minutes (465), matching 7h 45m as 7 * 60 + 45.
Related lubridate functions
- [
interval()](lubridate-interval-in-R.html) builds the Interval object thatint_length()measures - [
as.duration()](lubridate-duration-in-R.html) wraps the same second count in a Duration class with printed units time_length(int, "month")returns the length in a calendar aware unitint_start()andint_end()retrieve the bounds of the Intervalint_flip(int)reverses an interval soint_length()returns a positive number
FAQ
What unit does int_length() return in R?
int_length() always returns seconds as a plain numeric vector. There is no unit argument. Divide by 60 for minutes, 3600 for hours, or 86400 for days at 24 hour resolution. For calendar aware units like months or years, use time_length(int, "month") instead, since the average seconds per month is not constant across years.
Why does int_length() return a negative number?
The interval was built with the end timestamp before the start. lubridate preserves the direction of an Interval, so a reversed range produces a negative length rather than an error. Use abs(int_length(int)) to ignore direction, or call int_flip(int) to reorder the start and end. The negative is a feature for detecting ordering bugs, not a flaw.
What is the difference between int_length() and time_length()?
int_length(int) always returns seconds. time_length(int, unit) accepts a unit argument and returns the length in that unit, with calendar aware handling for "year" and "month". For "hour" or "minute", the two are equivalent up to a division. For "month" or "year", they disagree because time_length() knows that 2024 had 366 days while int_length() only sees raw seconds.
Can int_length() accept a Period or a Duration?
No. int_length() only works on Interval objects. Passing a Period or Duration throws Error: int is not an Interval. If you have a Duration, use as.numeric(d) to get seconds directly. If you have a Period, anchor it to a start date with interval(start, start + p) first, since a Period without an anchor has no defined number of seconds.
Is int_length() vectorised?
Yes. Pass a vector of Interval objects and int_length() returns a numeric vector of the same length. This makes it the standard pattern inside mutate(), sapply(), or any column expression that converts a pair of timestamp columns into a numeric duration column. No loop is needed.
For the full lubridate reference, see the official lubridate documentation.