class: center, middle, inverse, title-slide .title[ # Module 8-1 Demonstration ] .subtitle[ ## Special Operations: Dealing with date/time ] --- # Date-time Basics - Base R has functions to get the current date and time. - The `lubridate` package offers fast and user-friendly parsing of date-time data. .pull-left[ ``` r # get date information Sys.Date() ``` ``` ## [1] "2025-10-02" ``` ``` r # get current time Sys.time() ``` ``` ## [1] "2025-10-02 13:53:20 AEST" ``` ] .pull-right[ ``` r #install.packages("lubridate") library(lubridate) ``` ``` r # get current time using `lubridate` now() ``` ``` ## [1] "2025-10-02 13:53:20 AEST" ``` ] --- # Date-time manipulations - When date and time data are imported into R they will often default to: - a **factor** or **character** due to symbols such as `-`, `:` and `/` .pull-left[ ``` r candy <- read.csv("../data/candy_production.csv") head(candy,3) ``` ``` ## observation_date IPG3113N ## 1 1972-01-01 85.6945 ## 2 1972-02-01 71.8200 ## 3 1972-03-01 66.0229 ``` ``` r class(candy$observation_date) ``` ``` ## [1] "character" ``` ] .pull-right[ ``` r candy <- read.csv("../data/candy_production.csv", stringsAsFactors = TRUE) head(candy,3) ``` ``` ## observation_date IPG3113N ## 1 1972-01-01 85.6945 ## 2 1972-02-01 71.8200 ## 3 1972-03-01 66.0229 ``` ``` r class(candy$observation_date) ``` ``` ## [1] "factor" ``` ] --- # Date-time manipulations Cont. - Or sometimes they are converted into a **numeric (integer)** format: ``` r library(lubridate) head(lakers[, 1:4], 3) ``` ``` ## date opponent game_type time ## 1 20081028 POR home 12:00 ## 2 20081028 POR home 11:39 ## 3 20081028 POR home 11:37 ``` ``` r class(lakers$date) ``` ``` ## [1] "integer" ``` --- # Date-time manipulations Cont. - If this is the case, we need to convert these to proper date format. - We can use different strategies to convert them to a date format: - `as.Date()` function under Base R. - `lubridate` package functions --- # Convert factors to date with `as.Date()` ``` r candy <- read.csv("../data/candy_production.csv", stringsAsFactors = TRUE) head(candy,3) ``` ``` ## observation_date IPG3113N ## 1 1972-01-01 85.6945 ## 2 1972-02-01 71.8200 ## 3 1972-03-01 66.0229 ``` ``` r class(candy$observation_date) ``` ``` ## [1] "factor" ``` ``` r * candy_date <- as.Date(candy$observation_date) class(candy_date) ``` ``` ## [1] "Date" ``` --- # Convert strings to date with `as.Date()` ``` r candy <- read.csv("../data/candy_production.csv", stringsAsFactors = FALSE) head(candy,3) ``` ``` ## observation_date IPG3113N ## 1 1972-01-01 85.6945 ## 2 1972-02-01 71.8200 ## 3 1972-03-01 66.0229 ``` ``` r class(candy$observation_date) ``` ``` ## [1] "character" ``` ``` r * candy_date <- as.Date(candy$observation_date) class(candy_date) ``` ``` ## [1] "Date" ``` --- # Date-time manipulations Cont. - Note that the default date format is **YYYY-MM-DD**; therefore, if your string is of different format you must incorporate the `format` argument. - Have a look at these two examples: ``` r x <- c("08/03/2018", "23/03/2016", "30/01/2018") y <- c("08.03.2018", "23.03.2016", "30.01.2018") ``` - This time the string format is **DD/MM/YYYY** for `x` and **DD.MM.YYYY** for `y`; therefore, we need to specify the `format` argument explicitly. ``` r * x_date <- as.Date(x, format = "%d/%m/%Y") * y_date <- as.Date(y, format = "%d.%m.%Y") ``` <!-- - For format specifications type `?strftime` in your console. --> - [Useful link to Dates and Times in R](https://www.stat.berkeley.edu/~s133/dates.html) --- # Date-time manipulations with `lubridate` - The `lubridate` package can automatically recognise the common separators used when recording dates (`-`, `/`, `.`, and ` `). - As a result, you only need to focus on specifying the order of the date elements. For example: ``` r a <- c("26/03/2016", "08/12/2011", "05/01/2013") ``` - In order to convert `a` into a date, we can use `dmy()` (Day, Month, Year) ``` r library(lubridate) * a_date <- dmy(a) a_date ``` ``` ## [1] "2016-03-26" "2011-12-08" "2013-01-05" ``` --- # Date-time manipulations with `lubridate` - Here is the list of lubridate functions used for this purpose: Function | Order of elements in date-time ---------|-------------------------------- ymd() | year, month, day ydm() | year, day, month mdy() | month, day, year dmy() | day, month, year hm() | hour, minute hms() | hour, minute, second ymd_hms() | year, month, day, hour, minute, second --- # Your turn! Activity - Convert the following strings into a date format first using `as.Date()` and then `lubridate` functions. ``` r task1 <- c("08032018", "29062017", "23032016", "30012018") ``` ``` r task2 <- c("08}03}2018", "29}06}2017", "23}03}2016", "30}01}2018") ``` ``` r task3 <- c("08.03.2018", "29062017", "23/03/2016", "30-01-2018") ``` ??? ``` r task1 <- c("08032018", "29062017", "23032016", "30012018") # using as.Date date_task1 <- as.Date(task1, format = "%d%m%Y") class(date_task1) ``` ``` ## [1] "Date" ``` ``` r # using lubridate date_task1 <- dmy(task1) class(date_task1) ``` ``` ## [1] "Date" ``` ``` r task2 <- c("08}03}2018", "29}06}2017", "23}03}2016", "30}01}2018") # using as.Date date_task2 <- as.Date(task2, format = "%d}%m}%Y") class(date_task2) ``` ``` ## [1] "Date" ``` ``` r # using lubridate date_task2 <- dmy(task2) class(date_task2) ``` ``` ## [1] "Date" ``` ``` r task3 <- c("08.03.2018", "29062017", "23/03/2016", "30-01-2018") # using as.Date date_task3 <- as.Date(task3, format = c("%d.%m.%Y", "%d%m%Y", "%d/%m/%Y", "%d-%m-%Y")) date_task3 ``` ``` ## [1] "2018-03-08" "2017-06-29" "2016-03-23" "2018-01-30" ``` ``` r class(date_task3) ``` ``` ## [1] "Date" ``` ``` r # using lubridate date_task3 <- dmy(task3) class(date_task3) ``` ``` ## [1] "Date" ``` - As seen, lubridate is very flexible in recognising separators. --- # Extract & manipulate parts of dates - Sometimes, instead of a single string, we will have date-time spread across multiple columns. - Remember the flights data in the `nycflights13` package. ``` r library(nycflights13) head(flights[,c(1:3, 17:18)]) ``` ``` ## # A tibble: 6 × 5 ## year month day hour minute ## <int> <int> <int> <dbl> <dbl> ## 1 2013 1 1 5 15 ## 2 2013 1 1 5 29 ## 3 2013 1 1 5 40 ## 4 2013 1 1 5 45 ## 5 2013 1 1 6 0 ## 6 2013 1 1 5 58 ``` - Components of the date information is given in multiple columns. --- # Extract & manipulate parts of dates Cont. - To create a date/time from this sort of input, we can use `make_date()` for dates and `make_datetime()` for date-times. ``` ## # A tibble: 6 × 5 ## year month day hour minute ## <int> <int> <int> <dbl> <dbl> ## 1 2013 1 1 5 15 ## 2 2013 1 1 5 29 ## 3 2013 1 1 5 40 ## 4 2013 1 1 5 45 ## 5 2013 1 1 6 0 ## 6 2013 1 1 5 58 ``` ``` r *flights_new<- flights %>% mutate(departure = make_datetime(year, month, day, hour, minute)) head(flights_new$departure) ``` ``` ## [1] "2013-01-01 05:15:00 UTC" "2013-01-01 05:29:00 UTC" ## [3] "2013-01-01 05:40:00 UTC" "2013-01-01 05:45:00 UTC" ## [5] "2013-01-01 06:00:00 UTC" "2013-01-01 05:58:00 UTC" ``` --- # Extract & manipulate parts of dates Cont. - Conversely, we can extract individual parts of the date with the accessor functions in `lubridate`. Here is the list of available functions: Accessor Function | Extracts ------------------ | ---------- year() | year month() | month mday() | day of the month yday() | day of the year wday() | day of the week hour() | hour minute() | minute second() | second --- # Extract & manipulate parts of dates Cont. - To extract the year information of the `flights_new$departure` column we can use: ``` r flights_new$departure %>% year() %>% head() ``` ``` ## [1] 2013 2013 2013 2013 2013 2013 ``` - We can also use accessor functions to change the components of a date/time: ``` r # create a date datetime <- ymd_hms("2016-07-12 12:34:56") # replace the year component with 2025 year(datetime) <- 2025 # replace the month component with January month(datetime) <- 05 datetime ``` ``` ## [1] "2025-05-12 12:34:56 UTC" ``` --- # Date arithmetic - We may require to compute a new variable from the date - time information. - To calculate **time difference**, simply subtract two dates: ``` r my_age <- today() - ymd(19810529) my_age ``` ``` ## Time difference of 16197 days ``` - Or use `difftime()` function ``` r my_age <- difftime(today(), ymd(19810529)) my_age ``` ``` ## Time difference of 16197 days ``` - We get a **time intervals/differences object** (a.k.a `difftime` in R) --- # Date arithmetic Cont. - To change the time difference to another unit we can use `units` argument: ``` r my_age_secs<-difftime(today(), ymd(19810529), units = "secs") my_age_secs ``` ``` ## Time difference of 1399420800 secs ``` - `units` can be `"auto"`, `"secs"`, `"mins"`, `"hours"`, `"days"`, `"weeks"`. - Note that `difftime` objects do not accept **'years'** as a value for 'units', due to "leap years". - To get my age in years: ``` r my_age_days<-difftime(today(), ymd(19810529), units = "days") *my_age_years<- as.numeric(my_age_days/365) my_age_years ``` ``` ## [1] 44.37534 ``` --- # Date arithmetic Cont. - A sequence of dates/times can be created using `seq()` function with specifying four arguments `seq(from, to, by, length.out)`. ``` r # create a sequence of years from 1980 to 2024 by 2 even_years <- seq(from = 1980, to=2024, by = 2) even_years ``` ``` ## [1] 1980 1982 1984 1986 1988 1990 1992 1994 1996 1998 2000 2002 2004 2006 2008 ## [16] 2010 2012 2014 2016 2018 2020 2022 2024 ``` ``` r # create a sequence of hours from 1/1/2024 9:00 to 1/1/2024 12:00 hour_list <- seq(ymd_hm("2024-1-1 9:00"), ymd_hm("2024-1-1 12:00"), by = "hour") hour_list ``` ``` ## [1] "2024-01-01 09:00:00 UTC" "2024-01-01 10:00:00 UTC" ## [3] "2024-01-01 11:00:00 UTC" "2024-01-01 12:00:00 UTC" ``` --- # Date arithmetic: durations - A difftime class object records a time span of seconds, minutes, hours, days, or weeks. - `lubridate` provides an alternative which always uses seconds: the **duration**. Duration Function | Usage ------------------ | ---------- as.duration() | assigns duration in seconds is.duration() | check if it is duration dseconds | duration in seconds dminutes | duration in minutes dhours | duration in hours ddays | duration in days dweeks | duration in weeks dyears | duration in years - Minutes = 60 secs, hours = 3600 secs, days = 86400 secs, weeks = 604800 secs. --- # Date arithmetic: durations Cont. - With durations, date arithmetics would become easier: ``` r # three weeks later today() + dweeks(3) ``` ``` ## [1] "2025-10-23" ``` ``` r # tomorrow today() + ddays(1) ``` ``` ## [1] "2025-10-03" ``` ``` r # last year today() - dyears(1) ``` ``` ## [1] "2024-10-01 18:00:00 UTC" ``` --- # Date arithmetic: durations Cont. ``` r # two years, 12 weeks and 15 hours before today() - ( dyears(2) + dweeks(12) + dhours(15) ) ``` ``` ## [1] "2023-07-09 21:00:00 UTC" ``` ``` r #same as above: today() - ( 2*dyears(1) + dweeks(12) + dhours(15) ) ``` ``` ## [1] "2023-07-09 21:00:00 UTC" ``` --- # Your turn! Activity - Task 1: Set up 10 weekly meeting with your manager (start it from today) - Task 2: Find the weekday (i.e. Monday, Tuesday, Wednesday etc) of the day when you were born. ??? ``` r task1 <- today() + dweeks(0:9) task1 ``` ``` ## [1] "2025-10-02" "2025-10-09" "2025-10-16" "2025-10-23" "2025-10-30" ## [6] "2025-11-06" "2025-11-13" "2025-11-20" "2025-11-27" "2025-12-04" ``` ``` r task2 <- wday(dmy(29051981), label = T) task2 ``` ``` ## [1] Fri ## Levels: Sun < Mon < Tue < Wed < Thu < Fri < Sat ``` --- # Functions to Remember for Week 10 - Date/time manipulations using BaseR and `lubridate` - `as.Date()`, `ymd()`, `ydm()`, `mdy()`...etc. - `year()`, `month()`, `mday()`, `yday()`, `wday()`, ...etc. - duration functions: `duration()`, `dminutes()` , `dhours()`, ..etc - Practice! --- # Your turn! Class Worksheet <center><img src="../images/coding.gif" width="300px" /></center> - Working in small groups, complete the following class worksheet [Module 8-1 Worksheet](../worksheets/Week_10_Worksheet.html) - Once completed, feel free to work on your Assessments. <br> <br> <br> [Return to Course Website](../index.html)