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”.

DfT_birthday <- lubridate::as_date("1919-08-14")
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:

Table 6.1: Reported Road Accidents, 2017
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
road_accidents$Date1 <- lubridate::ymd(road_accidents$Date1)

# now check class
class(road_accidents$Date1)
#> [1] "Date"

6.1.2 Get year from date

Use the year function from {lubridate}:


road_accidents$Year <- lubridate::year(road_accidents$Date1)

See Table 5.2 for output

6.1.3 Get month from date

Use the month function from {lubridate}:


road_accidents$Month <- lubridate::month(road_accidents$Date1)

See Table 5.2 for output

6.1.4 Get day from date

Use the day function from {lubridate}:


road_accidents$Day <- lubridate::day(road_accidents$Date1)

See Table 5.2 for output

6.1.5 Get weekday from date

Use the wday function from {lubridate} to get the weekday label:


road_accidents$weekday <- lubridate::wday(road_accidents$Date1)

See Table 5.2 for output

6.1.6 Get quarter from date

Use the quarter function from {lubridate}:


road_accidents$Quarter <- lubridate::quarter(road_accidents$Date1)

See Table 5.2 for output

Table 6.2: Using lubridate to extract time information
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

Table 6.3: 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.


road_accidents$date_diff <- 
lubridate::as.duration(road_accidents$Date2 %--% road_accidents$Date1) / ddays(1)
Table 6.4: Find difference between two dates
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.


road_accidents$Month_lab <- month.abb[road_accidents$Month]
Table 6.5: Convert month to character
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.

 road_accidents$Month <- match(road_accidents$Month_lab,month.abb)
Table 6.6: Convert month character to integer
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.


road_accidents$date <- 
paste(road_accidents$Year, road_accidents$Month, road_accidents$Day, sep="-") %>% 
  ymd()%>%
  as.Date()
Table 6.7: Convert month to character
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
road_accidents$Date_time1 <- lubridate::ymd_hm(road_accidents$Date_time)

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.



road_accidents$Date2 <- lubridate::date(road_accidents$Date_time)

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.



road_accidents$Time <- hms::as_hms(road_accidents$Time)

6.2.4 Extract hour from time

Use the hour function from the {lubridate} package to extract hour information.



road_accidents$hour <- lubridate::hour(road_accidents$Time)

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.



road_accidents$minute <- lubridate::minute(road_accidents$Time)

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.



road_accidents$second <- lubridate::second(road_accidents$Time)

See Table 5.8 for output

Table 6.8: Extract time information
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
road_accidents$time2 <- paste(road_accidents$hour,road_accidents$minute, road_accidents$second, sep=":")
# convert to hms
road_accidents$time3 <- hms::as_hms(road_accidents$time2)
Table 6.9: Merge time information
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.


time_first <- hms::as.hms("11:00:00")
#> Warning: `as.hms()` was deprecated in hms 0.5.0.
#> ℹ Please use `as_hms()` instead.
time_second <- hms::as.hms("11:05:00")

difference <- difftime(time_first, time_second, "mins" )

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”


  1. a special date known as the Unix Epoch↩︎