Dates with lubridate

lubridate is the tidyverse package that makes working with dates and times painless — it parses messy date strings, pulls out components like year or weekday, and does calendar-aware arithmetic without fiddly format codes.

Learn Dates with lubridate in our free R course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free R course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll parse dates with ymd() / mdy() / dmy() , extract parts with year() and wday() , add durations and periods, snap dates with floor_date() , and handle time zones.

What You'll Learn in This Lesson

1️⃣ Parsing & Accessing Components

The parser functions are named for the order the parts appear in your text: ymd() for year-month-day, mdy() for US month/day/year, dmy() for day-month-year. They're forgiving about separators and even accept month names.

With a real Date in hand, accessor functions read off each component. With label = TRUE , weekday and month come back as readable names.

2️⃣ Date Arithmetic: Durations & Periods

Subtracting two dates gives a difftime (a span). To add time, lubridate offers two flavours: durations (exact seconds) and periods (human, calendar-aware units). The difference shows up around leap days and month ends.

Reach for periods ( months() , years() ) when you mean "same day next month/year," and durations ( ddays() , dyears() ) when you need an exact physical elapsed time.

3️⃣ Rounding Dates & Time Zones

floor_date() snaps a date down to a unit boundary — the heart of turning fine-grained timestamps into weekly or monthly groups. Time zones, meanwhile, live on date- times (POSIXct): attach one when parsing, then shift the wall-clock with with_tz() .

A key distinction: with_tz() keeps the same instant in time and changes only how it's displayed, whereas force_tz() keeps the displayed clock and changes the underlying instant. Mixing these up is the most common time-zone bug.

Your turn. Fill in the # TODO blanks and run it.

Parse timestamps with the right combined parser, label the weekdays, measure the span, and group by week — the full lifecycle of date wrangling in one task.

📋 Quick Reference — lubridate

Practice quiz

Which parser reads "03/15/2024" as month/day/year?

  • ymd()
  • mdy()
  • dmy()
  • ydm()

Answer: mdy(). lubridate parsers are named for component order; mdy() matches month/day/year.

Which parser handles "2024-03-15" (year-month-day)?

  • dmy()
  • mdy()
  • ymd()
  • myd()

Answer: ymd(). ymd() parses year-month-day order into a real Date.

What does wday(d, label = TRUE) return?

  • The day number only
  • The labelled weekday name
  • The year
  • The week of the year

Answer: The labelled weekday name. With label = TRUE, wday() returns the weekday as a readable name like Fri.

What is the difference between a period and a duration?

  • Periods are always shorter
  • There is no difference
  • Periods are exact seconds
  • Periods are calendar-aware; durations are exact seconds

Answer: Periods are calendar-aware; durations are exact seconds. Periods (months(), years()) respect the calendar; durations (ddays()) are fixed seconds.

Which adds exactly 30 calendar days to a date?

  • start + days(30)
  • start + 30s
  • start * 30
  • start + month(30)

Answer: start + days(30). days(30) is a period adding 30 calendar days.

What does floor_date(d, "month") do?

  • Adds a month
  • Removes the day
  • Snaps the date down to the first of its month
  • Rounds to the nearest year

Answer: Snaps the date down to the first of its month. floor_date snaps a date down to the start of the chosen unit, e.g. the month.

Which parser handles a date that also includes a time?

  • ymd_hms()
  • ymd()
  • hms()
  • time()

Answer: ymd_hms(). Add the time order to the name: ymd_hms() parses date plus hour-minute-second.

What does with_tz() change?

  • The underlying instant
  • Only the displayed wall-clock time zone
  • The date's year
  • Nothing

Answer: Only the displayed wall-clock time zone. with_tz() keeps the same instant and only changes how it is displayed.

Why parse a date string instead of leaving it as text?

  • It uses less memory
  • Text sorts and subtracts correctly
  • Parsing capitalizes months
  • So it sorts and subtracts correctly as a Date

Answer: So it sorts and subtracts correctly as a Date. A plain string sorts alphabetically; a real Date sorts and subtracts correctly.

What does ceiling_date(d, "month") return?

  • The start of the NEXT month
  • The end of the year
  • The same date
  • The previous month

Answer: The start of the NEXT month. ceiling_date snaps up to the next unit boundary, here the first of next month.