Dates and times with lubridate
Previous attendees have said…
- 4 previous attendees have left feedback
- 75% would recommend this session to a colleague
- 100% said that this session was pitched correctly

- All the content was very relevant. Found the run through a bit quick but I think I picked up most of it. A useful summary of the lubridate functions, thank-you.
- Nice introduction, examples and practice for using lubridate.
- Useful intro to lubridate. Sorry forgot to say in the session but would be interested to learn how to calculate time between dates. Ie age or time passed.
Slides
Session content
Word of warning
- dates and times are hard everywhere
- R is no exception
- this session is a beginner’s guide to lubridate
- not the only way of dealing with dates
- not always the best
- on balance the most consistent, and least quirky tools for dates
This session
- beginner-friendly
- focus on core parsing, get/set, and rounding functions
- lots on dates, a bit of date-times, no times
Resources
R dates
- days since 1970-01-01
as_date(0)[1] “1970-01-01”
R dates
as_date(19860)[1] “2024-05-17”
as_date(1:5)[1] “1970-01-02” “1970-01-03” “1970-01-04” “1970-01-05” “1970-01-06”
[1] “Date”
R date-times
- seconds since 1970-01-01 00:00:00 UTC
as_datetime(0)[1] “1970-01-01 UTC”
as_datetime(1715935369)[1] “2024-05-17 08:42:49 UTC”
as_datetime(0:5)[1] “1970-01-01 00:00:00 UTC” “1970-01-01 00:00:01 UTC” [3] “1970-01-01 00:00:02 UTC” “1970-01-01 00:00:03 UTC” [5] “1970-01-01 00:00:04 UTC” “1970-01-01 00:00:05 UTC”
class(as_datetime(0))[1] “POSIXct” “POSIXt”
Famously…
as_datetime(2 ^ 31-1) # 32 bit signed int[1] “2038-01-19 03:14:07 UTC”
Parsing dates is important
- most functions that accept dates (like ggplot) will mis-behave if you feed them date-shaped-words
- e.g. alphabetically-ordered dates
- we also want to be able to calculate with dates
Couple of fun intro functions
today()[1] “2026-05-18”
date_decimal(2024.37534)[1] “2024-05-17 08:59:11 UTC”
now()[1] “2026-05-18 10:54:31 BST”
now("Japan")[1] “2026-05-18 18:54:31 JST”
random_zone <- sample(OlsonNames(), 1)
cat(paste("The date-time in", random_zone, "is", now(sample(OlsonNames(), 1))))The date-time in America/Argentina/Ushuaia is 2026-05-18 06:54:31.56886
Parsing
-
as_date()is fine assuming you have your date as a number of days - but usually, we’ll need to parse our dates
as_date(45429) # excel-format 1900 date[1] “2094-05-19”
as_date(45429 - 25569) # dirty but effective[1] “2024-05-17”
as_date(45429, origin = "1899-12-30") # better[1] “2024-05-17”
Parsing
- more often, we’ll be taking human-readable dates and parsing them
- that’s a pain, because there are loads of inconsistent ways of representing dates
- worse, lots of dates are ambiguous (5/6/24 and 6/5/24 might refer to the same day)
[1] “2017-05-24” “2024-05-17” NA “2017-05-24” NA
# one correct, two silently incorrent, two NAsparse_date_time
parse_date_time(date_input, orders = "ymd")[1] “2017-05-24 UTC” “2024-05-17 UTC” NA “2017-05-24 UTC” [5] NA
parse_date_time(date_input, orders = c("dmy", "ymd", "dmy", "dmy", "mdy"))[1] “2024-05-17 UTC” “2024-05-17 UTC” “2024-05-17 UTC” “2024-05-17 UTC” [5] “2024-05-17 UTC”
dmy and co
- you can also use the orders (like dmy) as standalone parsing functions:
[1] “2024-05-17” “2024-05-17” “2024-05-17”
ymd_hms("2024-05/17 9-05-01")[1] “2024-05-17 09:05:01 UTC”
So you can make dates/date-times. So what?
[1] “2026-05-18”
[1] 2026
[1] FALSE
[1] 2
[1] 1
[1] 2026.1
Months and weeks
[1] 5
[1] May 12 Levels: Jan < Feb < Mar < Apr < May < Jun < Jul < Aug < Sep < … < Dec
[1] 20
[1] 20
Days
[1] 18
[1] 2
[1] 48
Hour and minute
[1] 10
[1] 54
[1] TRUE
[1] TRUE
Set
[1] “2026-05-18 11:00:00 BST”
- or, more generally:
[1] 5
day(test_date) <- 11
test_date[1] “2023-06-11”
Round
floor_date(today(), unit = "week")[1] “2026-05-17”
round_date(today(), unit = "week")[1] “2026-05-17”
ceiling_date(today(), unit = "month")[1] “2026-06-01”
[1] “2026-04-30”