lubridate minutes() in R: Create Minute-Based Time Periods
The minutes() function in lubridate builds a minute-based Period object you can add to or subtract from a datetime. It is vectorised, calendar-aware, and lets you shift timestamps by N minutes without hand-rolling seconds arithmetic.
ymd_hms("2024-07-15 09:00:00") + minutes(30) # add 30 minutes
ymd_hms("2024-07-15 09:00:00") - minutes(15) # subtract 15 minutes
now() + minutes(c(5, 15, 60)) # vectorised shifts
hours(1) + minutes(30) # combine components
class(minutes(5)) # "Period" object
as.numeric(minutes(90), "seconds") # 5400 seconds
ymd_hms("2024-07-15 23:50:00") + minutes(20) # cross-hour shift
df %>% mutate(eta = start + minutes(wait_min)) # use in dplyrNeed explanation? Read on for examples and pitfalls.
What minutes() does in one sentence
minutes(n) returns a Period object representing n minutes of clock time. Pass an integer or numeric vector and you get a period whose minute slot equals the input, ready to add to a POSIXct or Date value.
This is a constructor, not an accessor. It builds time spans you can do arithmetic with. If you want to read the minute component out of an existing datetime, you want minute() (singular), covered in lubridate minute() in R.
Syntax
minutes(x = 1) takes a numeric vector and returns a Period of the same length. There is one argument and one return type. The output prints as "30M 0S" and behaves like a clock offset in datetime arithmetic.
The period prints with the minute and second components populated and the larger units hidden. You can mix it with other constructors like hours() and seconds() to build richer spans.
Period is calendar-aware. A Period from minutes() adds wall-clock minutes, whereas a Duration from dminutes() adds physical seconds. The two agree except across daylight-saving transitions where their hour boundaries diverge.Six common patterns with minutes()
1. Add minutes to a single datetime
Use + minutes(n) to push a timestamp forward by n minutes. The result is a POSIXct value with the same timezone as the input.
Negative inputs work too: minutes(-10) is equivalent to -minutes(10). The arithmetic is exact because Period carries minutes as a separate slot rather than reducing them to seconds.
2. Vectorised minute arithmetic
Both sides of the + operator can be vectors. This makes batch reminder offsets a single expression.
The result is the same length as the longer of the two operands. R recycles the shorter vector when their lengths are compatible.
3. Cross-hour shifts
minutes() rolls into the next hour cleanly. You do not need a separate hours() call for shifts of 60 or more minutes.
Large minute counts (minutes(180)) work as well, though hours(3) reads more clearly for human consumers. Pick the unit that matches how the input is stored.
4. Build multi-component periods
Add period constructors together to express compound spans. hours(1) + minutes(30) reads like English and prints as "1H 30M 0S".
This composes well when the offset comes from a schedule string or user form that supplies hours and minutes separately.
5. Use minutes() inside dplyr pipelines
minutes() plugs into mutate() for row-wise schedule arithmetic. Pair it with a numeric wait-time column to compute reminder or ETA timestamps.
Integer inputs are preferred. Lubridate treats fractional minutes as exact when stored in the period but some downstream printers may round, so for sub-minute precision combine minutes() with seconds() explicitly.
6. Convert minutes() to other units
Coerce a period to seconds with as.numeric(period, "seconds") when an API expects raw seconds. This is the standard bridge between lubridate periods and base R offsets.
period_to_seconds() is the explicit helper if you prefer named verbs over as.numeric() coercion. Both return the same value.
minutes() vs dminutes(): period vs duration
minutes() adds clock-time minutes; dminutes() adds exactly 60 seconds per unit. The two functions agree almost everywhere and diverge only across daylight-saving transitions when a minute window straddles the jump.
Outside DST the two are identical. Inside a spring-forward hour, dminutes() keeps elapsed seconds exact while minutes() keeps the wall clock honest. Pick the one that matches your mental model.
| Aspect | minutes() (Period) |
dminutes() (Duration) |
|---|---|---|
| Unit | Clock minutes | Physical seconds |
| DST behaviour | Adds wall minutes | Adds exactly 60 s per unit |
| Print form | "30M 0S" |
"1800s (~30 minutes)" |
| Use when | Human schedules, reminders | Elapsed timing, stopwatch math |
| Class | Period |
Duration |
minutes() for human reminders, dminutes() for stopwatch math. A reminder set "30 minutes from now" should use minutes(30) so it fires at the same wall-clock minute after a DST flip. A reactor that ran "90 minutes" should use dminutes(90) so the elapsed seconds match the physical clock.minutes() vs minute(): constructor vs accessor
minutes() builds a span; minute() reads a component. They are independent functions and a frequent source of confusion for newcomers.
If you write ts + minute(15) (singular) you almost certainly meant ts + minutes(15). The singular form returns an integer, not a period, and the addition silently treats it as seconds.
Common pitfalls
Three patterns trip up most users. Knowing them up front saves debugging later.
start + 30 advances by 30 seconds, not 30 minutes. Always wrap the number in minutes() to get the unit you expect.The second pitfall is mixing periods and durations in one expression. minutes(1) + dminutes(1) works but the result coerces the duration into a period. Stick to one family per calculation to avoid surprises around DST.
The third pitfall is naive timezones. If your input has no tz, lubridate assumes UTC and your "9 AM" may print as 4 AM after a with_tz() conversion. Set tz = "America/New_York" (or your locale) at parse time so the minute arithmetic lands where you expect.
Try it yourself
Try it: Build a tibble of three meeting start times. Add a wait_min column with values 10, 15, and 45. Compute the reminder timestamp for each meeting using minutes(). Save the tibble to ex_reminders.
Click to reveal solution
Explanation: mutate() evaluates start + minutes(wait_min) row-wise, building a Period from each numeric wait time and adding it to the matching start timestamp.
Related lubridate functions
A handful of neighbouring constructors round out minute arithmetic. Reach for these when minutes() is not the right shape.
- hours() and
seconds(): larger and smaller period constructors. Combine withminutes()for compound spans. days(),weeks(),months(),years(): calendar-grain period constructors. Same arithmetic model.dminutes(),dhours(),dseconds(): duration siblings. Use when you need exact second counts across DST.- minute(): the accessor that reads the minute-of-hour from a datetime.
hms(),hm(), andms(): parse"HH:MM:SS","HH:MM", and"MM:SS"strings intoPeriodobjects.period(): generic period constructor with named arguments, e.g.,period(30, "minutes").
For the full lubridate reference, see the official lubridate docs.
FAQ
What does minutes() do in R?
minutes(n) from the lubridate package returns a Period object representing n minutes of clock time. You add or subtract it from a POSIXct or Date value to shift the timestamp by that many minutes. The result respects daylight-saving boundaries because periods track wall-clock minutes rather than raw elapsed seconds.
What is the difference between minute() and minutes() in lubridate?
minute() is an accessor: it reads the minute-of-hour (0 to 59) out of a datetime and returns an integer. minutes() is a constructor: it builds a Period you can add to a datetime to shift it forward or backward. The plural form is for arithmetic; the singular form is for inspection.
How do I add minutes to a datetime in R?
Use your_datetime + minutes(n). For example, ymd_hms("2024-07-15 09:00:00") + minutes(30) returns "2024-07-15 09:30:00 UTC". The + operator is overloaded to recognise lubridate Period objects, so the arithmetic reads like plain math without manual second conversion.
What is the difference between Period and Duration in lubridate?
A Period (from minutes(), hours(), days()) tracks clock units and preserves wall-clock time across daylight-saving transitions. A Duration (from dminutes(), dhours(), ddays()) tracks physical seconds and stays exact across DST. Use periods for human schedules and durations for elapsed-time calculations.
Can I use fractional minutes with minutes()?
Fractional inputs like minutes(2.5) are accepted but for sub-minute precision the readable pattern is minutes(2) + seconds(30). Splitting the components keeps the period's printed form predictable and avoids edge cases where downstream code rounds fractional minute slots.