Chapter 6 Working with dates and times
This chapter provides an overview of working with dates and times, for example extracting year or month from a date, and converting characters to a date.
One of the main packages used to work with dates is {lubridate}.
More information can be found on the {lubridate} cheatsheet at the following link: https://www.rstudio.com/resources/cheatsheets/
Date vectors are just vectors of class double with an additional class attribute set as “Date”.
<- lubridate::as_date("1919-08-14")
DfT_birthday typeof(DfT_birthday)
#> [1] "double"
attributes(DfT_birthday)
#> $class
#> [1] "Date"
If we remove the class using unclass()
we can reveal the value of the double, which is the number of days since “1970-01-01”3, since DfT’s birthday is before this date, the double is negative.
unclass(DfT_birthday)
#> [1] -18403
This chapter will be using the road accident data set:
acc_index | Date | Police_Force | Day_of_Week | Time |
---|---|---|---|---|
2017010001708 | 2017-08-05 | 1 | 7 | 1899-12-31 03:12:00 |
2017010009342 | 2017-01-01 | 1 | 1 | 1899-12-31 01:30:00 |
2017010009344 | 2017-01-01 | 1 | 1 | 1899-12-31 00:30:00 |
2017010009348 | 2017-01-01 | 1 | 1 | 1899-12-31 01:11:00 |
2017010009350 | 2017-01-01 | 1 | 1 | 1899-12-31 01:42:00 |
2017010009351 | 2017-01-01 | 1 | 1 | 1899-12-31 03:31:00 |
6.1 Working with dates
6.1.1 Converting a character to a date
In R, dates can be converted to a specific date variable type in order to use the variable as a date.
Having a variable as a date means that you can:
- extract the different elements of the date (year, month etc.)
- calculate differences between dates
This can be done in the following way:
- Identify the order of the year, month, day and use the appropriate function (ymd, mdy, dmy etc.)
# convert date to date object
# check class of date
class(road_accidents$Date1)
#> [1] "character"
# look at the date variable and see what order it is in (year-m-d)
# therefore use the ymd function
$Date1 <- lubridate::ymd(road_accidents$Date1)
road_accidents
# now check class
class(road_accidents$Date1)
#> [1] "Date"
6.1.2 Get year from date
Use the year function from {lubridate}:
$Year <- lubridate::year(road_accidents$Date1) road_accidents
See Table 5.2 for output
6.1.3 Get month from date
Use the month function from {lubridate}:
$Month <- lubridate::month(road_accidents$Date1) road_accidents
See Table 5.2 for output
6.1.4 Get day from date
Use the day function from {lubridate}:
$Day <- lubridate::day(road_accidents$Date1) road_accidents
See Table 5.2 for output
6.1.5 Get weekday from date
Use the wday function from {lubridate} to get the weekday label:
$weekday <- lubridate::wday(road_accidents$Date1) road_accidents
See Table 5.2 for output
6.1.6 Get quarter from date
Use the quarter function from {lubridate}:
$Quarter <- lubridate::quarter(road_accidents$Date1) road_accidents
See Table 5.2 for output
Date1 | Year | Quarter | Month | Day | weekday |
---|---|---|---|---|---|
2017-08-05 | 2017 | 3 | 8 | 5 | 7 |
2017-01-01 | 2017 | 1 | 1 | 1 | 1 |
2017-01-01 | 2017 | 1 | 1 | 1 | 1 |
2017-01-01 | 2017 | 1 | 1 | 1 | 1 |
2017-01-01 | 2017 | 1 | 1 | 1 | 1 |
2017-01-01 | 2017 | 1 | 1 | 1 | 1 |
6.1.7 Find difference between two dates
acc_index | Date1 | Date2 |
---|---|---|
2017010001708 | 2017-08-05 | 2017-08-01 |
2017010009342 | 2017-01-01 | 2017-01-01 |
2017010009344 | 2017-01-01 | 2017-01-01 |
2017010009348 | 2017-01-01 | 2017-01-01 |
2017010009350 | 2017-01-01 | 2017-01-01 |
2017010009351 | 2017-01-01 | 2017-01-01 |
Use the as.duration function to find the duration between two dates. The duration to be measured can be specified:
- dhours
- dweeks
- ddays
- dminutes
- dyears
To find out the number of days difference, the as.duration function calculates the duration in seconds so the duration must be divided by the desired duration (ddays) to convert to duration in days.
$date_diff <-
road_accidents::as.duration(road_accidents$Date2 %--% road_accidents$Date1) / ddays(1) lubridate
acc_index | Date1 | Date2 | date_diff |
---|---|---|---|
2017010001708 | 2017-08-05 | 2017-08-01 | 4 |
2017010009342 | 2017-01-01 | 2017-01-01 | 0 |
2017010009344 | 2017-01-01 | 2017-01-01 | 0 |
2017010009348 | 2017-01-01 | 2017-01-01 | 0 |
2017010009350 | 2017-01-01 | 2017-01-01 | 0 |
2017010009351 | 2017-01-01 | 2017-01-01 | 0 |
The %--%
operator is used to define an interval. So, this code is calculating the duration of the interval between Date2
and Date1
.
The number after ddays indicates by how many units the duration is (i.e. one day).
6.1.8 Convert month (integer to character)
{base} R has a useful function which takes the month numbers and converts them to the corresponding text.
$Month_lab <- month.abb[road_accidents$Month] road_accidents
acc_index | Date | Month | Month_lab |
---|---|---|---|
2017010001708 | 2017-08-05 | 8 | Aug |
2017010009342 | 2017-01-01 | 1 | Jan |
2017010009344 | 2017-01-01 | 1 | Jan |
2017010009348 | 2017-01-01 | 1 | Jan |
2017010009350 | 2017-01-01 | 1 | Jan |
2017010009351 | 2017-01-01 | 1 | Jan |
6.1.9 Convert month (character to integer)
{base} R has a useful function which takes the month text and converts them to the corresponding number.
$Month <- match(road_accidents$Month_lab,month.abb) road_accidents
acc_index | Date | Month | Month_lab |
---|---|---|---|
2017010001708 | 2017-08-05 | 8 | Aug |
2017010009342 | 2017-01-01 | 1 | Jan |
2017010009344 | 2017-01-01 | 1 | Jan |
2017010009348 | 2017-01-01 | 1 | Jan |
2017010009350 | 2017-01-01 | 1 | Jan |
2017010009351 | 2017-01-01 | 1 | Jan |
6.1.10 Merge separate date information into a date
The {lubridate} package can be used in conjunction with the paste function to combine columns separate date information (e.g. year, month, day) into one date variable.
$date <-
road_accidentspaste(road_accidents$Year, road_accidents$Month, road_accidents$Day, sep="-") %>%
ymd()%>%
as.Date()
acc_index | Date | Year | Month | Day | date |
---|---|---|---|---|---|
2017010001708 | 2017-08-05 | 2017 | 8 | 5 | 2017-08-05 |
2017010009342 | 2017-01-01 | 2017 | 1 | 1 | 2017-01-01 |
2017010009344 | 2017-01-01 | 2017 | 1 | 1 | 2017-01-01 |
2017010009348 | 2017-01-01 | 2017 | 1 | 1 | 2017-01-01 |
2017010009350 | 2017-01-01 | 2017 | 1 | 1 | 2017-01-01 |
2017010009351 | 2017-01-01 | 2017 | 1 | 1 | 2017-01-01 |
6.2 Working with date-times
A date-time stores date and time information.
6.2.1 Converting a character to a date-time
This is similar to converting a character to a date as mentioned above.
This can be done in the following way:
- Identify the order of the year, month, day, and time elements (hour, minute and second or just hour and minute) and use the appropriate function (ymd, mdy, dmy etc.)
# convert date to date object
# look at the date variable and see what order it is in (year-m-d, hms "2017-11-28 14:00)
# therefore use the ymd_hm
$Date_time1 <- lubridate::ymd_hm(road_accidents$Date_time) road_accidents
6.2.2 Extract date from date time variable
Use the date function to extract the date from a date time variable.
The year/month/day information can then be extracted from the date using the code examples above.
$Date2 <- lubridate::date(road_accidents$Date_time) road_accidents
6.2.3 Convert character to hms (time) variable
Convert time as character into a hms variable so the variable can manipulated as a time object.
This can be done using the {hms} package.
$Time <- hms::as_hms(road_accidents$Time) road_accidents
6.2.4 Extract hour from time
Use the hour function from the {lubridate} package to extract hour information.
$hour <- lubridate::hour(road_accidents$Time) road_accidents
See Table 5.8 for output
6.2.5 Extract minute from time
Use the minute function from the {lubridate} package to extract minute information.
$minute <- lubridate::minute(road_accidents$Time) road_accidents
See Table 5.8 for output
6.2.6 Extract second from time
Use the second function from the {lubridate} package to extract second information.
$second <- lubridate::second(road_accidents$Time) road_accidents
See Table 5.8 for output
acc_index | Time | hour | minute | second |
---|---|---|---|---|
2017010001708 | 03:12:00 | 3 | 12 | 0 |
2017010009342 | 01:30:00 | 1 | 30 | 0 |
2017010009344 | 00:30:00 | 0 | 30 | 0 |
2017010009348 | 01:11:00 | 1 | 11 | 0 |
2017010009350 | 01:42:00 | 1 | 42 | 0 |
2017010009351 | 03:31:00 | 3 | 31 | 0 |
6.2.7 Merge separate time information into one variable
Hour, minute and second variables can be merged to create a time variable, and then converted to hms.
# merge seperate time information
$time2 <- paste(road_accidents$hour,road_accidents$minute, road_accidents$second, sep=":") road_accidents
# convert to hms
$time3 <- hms::as_hms(road_accidents$time2) road_accidents
acc_index | hour | minute | second | time2 |
---|---|---|---|---|
2017010001708 | 3 | 12 | 0 | 3:12:0 |
2017010009342 | 1 | 30 | 0 | 1:30:0 |
2017010009344 | 0 | 30 | 0 | 0:30:0 |
2017010009348 | 1 | 11 | 0 | 1:11:0 |
2017010009350 | 1 | 42 | 0 | 1:42:0 |
2017010009351 | 3 | 31 | 0 | 3:31:0 |
6.2.8 find the difference between two times
Use the {base} r difftime function to find the difference between two times.
Note: this can also be used to find the difference in days or weeks.
Also note: the object must be hms/date to be able to calculate the difference.
<- hms::as.hms("11:00:00")
time_first #> Warning: `as.hms()` was deprecated in hms 0.5.0.
#> ℹ Please use `as_hms()` instead.
<- hms::as.hms("11:05:00")
time_second
<- difftime(time_first, time_second, "mins" ) difference
difference#> Time difference of -5 mins
Change the unit of measurement to get different time differences (for days and weeks you’ll need a date rather than a hms).
Units: “secs”, “mins”, “hours”, “days”, “weeks”
a special date known as the Unix Epoch↩︎