---
title: Dates and times
author: David Kane and Mann Talati
tutorial:
  id: dates-and-times
output:
  learnr::tutorial:
    progressive: yes
    allow_skip: yes
runtime: shiny_prerendered
description: 'Tutorial for Chapter 17: Dates and times'
---

```{r setup, include = FALSE}
library(learnr)
library(tutorial.helpers)
library(tidyverse)
library(nycflights13)

knitr::opts_chunk$set(echo = FALSE)
options(tutorial.exercise.timelimit = 60, 
        tutorial.storage = "local") 

make_datetime_100 <- function(year, month, day, time) {
  make_datetime(year, month, day, time %/% 100, time %% 100)
}

flights_dt <- flights |> 
  filter(!is.na(dep_time), !is.na(arr_time)) |> 
  mutate(
    dep_time = make_datetime_100(year, month, day, dep_time),
    arr_time = make_datetime_100(year, month, day, arr_time),
    sched_dep_time = make_datetime_100(year, month, day, sched_dep_time),
    sched_arr_time = make_datetime_100(year, month, day, sched_arr_time)
  ) |> 
  select(origin, dest, ends_with("delay"), ends_with("time"))

date2015 <- "
  date
  01/02/15
"



datetime2026 <- ymd_hms("2026-07-08 12:34:56")
age <- today() - ymd("2000-8-30") 
date2026 <- ymd_hms("2026-03-08 01:00:00", tz = "America/New_York")
date2021 <- ymd("2021-01-01")
date2020 <- ymd("2020-01-01")
interval <- date2020 %--% date2021
newyorkdate <- ymd_hms("2023-06-20 12:00:00", tz = "America/New_York")
parisdate <- ymd_hms("2023-06-20 18:00:00", tz = "Europe/Paris")
combined <- c(parisdate, newyorkdate)
```

```{r copy-code-chunk, child = system.file("child_documents/copy_button.Rmd", package = "tutorial.helpers")}
```

```{r info-section, child = system.file("child_documents/info_section.Rmd", package = "tutorial.helpers")}
```

<!-- DK: This tutorial is sloppy throughout. Fixing it is a high priority. -->

## Introduction
### 

This tutorial covers [Chapter 17: Dates and times](https://r4ds.hadley.nz/datetimes.html) from [*R for Data Science (2e)*](https://r4ds.hadley.nz/) by Hadley Wickham, Mine Çetinkaya-Rundel, and Garrett Grolemund. You will learn how to use the [**lubridate**](https://lubridate.tidyverse.org/) on the `flights` data from the [**nyc13flights**](https://nycflights13.tidyverse.org/) package.


## Creating date/times through import
### 

In this chapter we are going to focus on dates and date-times as R doesn’t have a native class for storing times. If you need one, you can use the **hms** package. `hms()` stands for **h**our, **m**inute, **s**econd.   

### Exercise 1

Let's load the **tidyverse** library. 

```{r creating-date-times-through-im-1, exercise = TRUE}

```

```{r creating-date-times-through-im-1-hint-1, eval = FALSE}
library(...)
```

### Exercise 2

Run `today()` in the code chunk below. With this we can get the current date.

```{r creating-date-times-through-im-2, exercise = TRUE}

```

```{r creating-date-times-through-im-2-hint-1, eval = FALSE}
...()
```

### 

The above code printed a date. 

### Exercise 3

Run `now()` in the code chunk below. With this we can get the current date-time.

```{r creating-date-times-through-im-3, exercise = TRUE}

```

```{r creating-date-times-through-im-3-hint-1, eval = FALSE}
...()
```

### 

A date-time is a date plus a time: it uniquely identifies an instant in time (typically to the nearest second). Tibbles print this as `<dttm>`. Base R calls these POSIXct, but doesn’t exactly trip off the tongue.


### Exercise 4

Enter `date2015` and hit "Run Code".

```{r creating-date-times-through-im-4, exercise = TRUE}

```

```{r creating-date-times-through-im-4-hint-1, eval = FALSE}
date2015
```

`date2015` is a character vector with a single element which includes both the variable name, `date` and, after a newline character, a value: `01/02/15`.

### Exercise 5

Run `read_csv()` on `date2015`.

```{r creating-date-times-through-im-5, exercise = TRUE}

```

```{r creating-date-times-through-im-5-hint-1, eval = FALSE}
read_csv(...)
```

```{r creating-date-times-through-im-5-test, include = FALSE}
read_csv(date2015)
```

### 

With `read_csv()` we are able to analyze the aspects of date and date-time with `col_types` such as `col_date()`, and `col_datetime()`. We can view the year features, month features, day features, time features, and other features.

### Exercise 6

Now we will use `col_types` to format the date in the `date2015`. Set `col_types` to `cols(date = col_date("%m/%d/%y"))` in `read_csv()`.

```{r creating-date-times-through-im-6, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-date-times-through-im-6-hint-1, eval = FALSE}
read_csv(date2015, ... = cols(date = col_date("%m/%d/%y")))
```

```{r creating-date-times-through-im-6-test, include = FALSE}
read_csv(date2015, col_types = cols(date = col_date("%m/%d/%y")))
```

### 

With this we can see a tibble that formats our date in year/month/day format.

### Exercise 7

Let's try a different format. Set `col_types` to `cols(date = col_date("%d/%m/%y"))` in `read_csv()`.

```{r creating-date-times-through-im-7, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-date-times-through-im-7-hint-1, eval = FALSE}
read_csv(date2015, col_types = ...)
```

```{r creating-date-times-through-im-7-test, include = FALSE}
read_csv(date2015, col_types = cols(date = col_date("%d/%m/%y")))
```

### 

Note that no matter how you specify the date format, it’s always displayed the same way once you get it into R.

### 

Oftentimes when working with non-English dates and %b or %B you will need to use `locale()`. Check out [**date_names_langs()**](https://readr.tidyverse.org/reference/date_names.html) for more information.

## Creating date/times with strings
### 

The date-time specification language is powerful, but requires careful analysis of the date format. An alternative approach is to use lubridate’s helpers which attempt to automatically determine the format once you specify the order of the component.

### Exercise 1

Run `mdy()` on "January 31st, 2017".

```{r creating-date-times-with-strin-1, exercise = TRUE}

```

```{r creating-date-times-with-strin-1-hint-1, eval = FALSE}
...("January 31st, 2017")
```

### Exercise 2

Run `ymd()` on "2017-01-31".

```{r creating-date-times-with-strin-2, exercise = TRUE}

```

```{r creating-date-times-with-strin-2-hint-1, eval = FALSE}
ymd(...)
```

### 

When using these three formats we need to identify the order in which year, month, and day appear in your dates, then arrange “y”, “m”, and “d” in the same order. That gives you the name of the lubridate function that will parse your date.

### Exercise 3

Besides this we can also force set this by supplying a timezone. In `ymd()` set `tz` to "EST".

```{r creating-date-times-with-strin-3, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-date-times-with-strin-3-hint-1, eval = FALSE}
ymd("2017-01-31", tz = ...)
```

### Exercise 4

We can also use the "hms" function to create an datetime. Set `ymd_hms()` to "2017-01-31 20:11:59".

```{r creating-date-times-with-strin-4, exercise = TRUE}

```

```{r creating-date-times-with-strin-4-hint-1, eval = FALSE}
ymd_hms(...)
```

### 

With this we are able to create a datetime that is automatically set to UTC. The UTC timezone known as GMT, or Greenwich Mean Time, doesn't use daylight saving time, making it a bit easier to compute with.

## Creating dates and times with individual components
### 

We can use the datetime features on pieces of data. We will use the datetime component on the `flights` data.

### 

Let's make this line graph using `geom_point()`:

```{r creating-datetimes-w}
flight_grph <- 
  flights |>
    mutate(dep_time = make_datetime(year, month, day, dep_time),
            sched_dep_time = make_datetime(year, month, day, sched_dep_time)) |>
    select(dep_delay, dep_time, sched_dep_time) |> 
    drop_na() |> 
    ggplot(aes(x = sched_dep_time, 
               y = dep_time,
               color = dep_delay)) +
      geom_point() +
      labs(title = "Flights",
           subtitle = "Flight departed time based on scheduled departed time.",
           color = "Flight",
           x = "Scheduled Departure Time",
           y = "Departure Time")

flight_grph
```

### Exercise 1

Run `glimpse()` on `flights`.

```{r creating-dates-and-times-with-1, exercise = TRUE}

```

```{r creating-dates-and-times-with-1-hint-1, eval = FALSE}
glimpse(...)
```

### 

Here we can see all of the flights from NYC to destinations in the United States territories in 2013: 336,776 flights in total. Pay close attention to the `dep_time`, `sched_dep_time`, and `dep_delay`.

### Exercise 2

Let's start a pipe with the `flights` data. Mutate the `flights` data to set `dep_time` to `make_datetime(year, month, day, dep_time)`.

```{r creating-dates-and-times-with-2, exercise = TRUE}

```

```{r creating-dates-and-times-with-2-hint-1, eval = FALSE}
flights |>
  mutate(dep_time = make_datetime(..., ..., ..., dep_time))
```

### 

Here we are able to make a datetime for the departure time based on the `year`, `month`, `day` and the departure of each plane. When creating a a date/time from this sort of input, we use `make_date()` for dates, or `make_datetime()` for date-times.

### Exercise 3

Let's add to the `mutate()` and set `sched_dep_time` to `make_datetime(year, month, day, sched_dep_time)`.

```{r creating-dates-and-times-with-3, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-3-hint-1, eval = FALSE}
... |>
    mutate(...,
           sched_dep_time = ...))
```

### 

Similar to above, we created a datetime based on the scheduled departure time for each plane.

### Exercise 4

Continue the pipe by adding `select()` for the `dep_delay`, `dep_time`, `sched_dep_time` variables

```{r creating-dates-and-times-with-4, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-4-hint-1, eval = FALSE}
... |>
    mutate(...,
           sched_dep_time = ...)) |>
    select(dep_delay, dep_time, sched_dep_time)
```

### 

We only want to select these three variables because we will be using these for our graph.

### Exercise 5

Continue the pipe by adding `ggplot()` and in `aes()` set `x` to `sched_dep_time` and `y` to `dep_time`

```{r creating-dates-and-times-with-5, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-5-hint-1, eval = FALSE}
... |>
    ggplot(aes(x = ..., 
               y = ...))
```

Note nothing will be plotted because we have not used `geom_point()`.

### Exercise 6

Let's plot this by adding `geom_point()`.

```{r creating-dates-and-times-with-6, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-6-hint-1, eval = FALSE}
... |>
  ... +
  geom_point()
```

### 

You should have recieved a warning message that says: Warning message:
Removed 8255 rows containing missing values (`geom_point()`). We will solve this issue by using `drop_na()`.

### Exercise 7

We want to add drop any null values from the three columns that we use. Continue the pipe after `select()` to add `drop_na()`.

```{r creating-dates-and-times-with-7, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-7-hint-1, eval = FALSE}
... |>
  select(...) |>
    ...()
```

### Exercise 8

In `aes()` set `color` to `dep_delay`.

```{r creating-dates-and-times-with-8, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-8-hint-1, eval = FALSE}
ggplot(aes(x = ..., 
           y = ...,
           color = ...))
```

### 

When we set `color` to `dep_delay` we are able to see how late flights were regarding departure times.

### Exercise 9

Finally add the labels to the graph to complete the graph with `labs()`

```{r creating-dates-and-times-with-9, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r creating-dates-and-times-with-9-hint-1, eval = FALSE}
+ labs(title = ...,
                subtitle = ...,
                color = "Flight",
                x = ...,
                y = ...)
```

Remember your graph should look like this:

```{r flight_grph}
flight_grph
```

### 

When we want to switch between date and datetime we use `as_datetime()` and `as_date()`. Visit [**as_datetime()**](https://lubridate.tidyverse.org/reference/as_date.html) for more information.

## Date-time components with getting components
### 

You can pull out individual parts of the date with the accessor functions `year()`, `month()`, `mday()` (day of the month), `yday()` (day of the year), `wday()` (day of the week), `hour()`, `minute()`, and `second()`. These are effectively the opposites of `make_datetime()`.

### 

We are going to use the `flights_dt` dataset which includes the `dep_time`, `sched_dep_time`, `arr_time`, `sched_arr_time` which are datetimes.

### Exercise 1

Run `glimpse()` on `flights_dt` to look at the data.

```{r datetime-components-with-getti-1, exercise = TRUE}

```

```{r datetime-components-with-getti-1-hint-1, eval = FALSE}
glimpse(...)
```

### 

We are going to focus on four columns `dep_time`, `sched_dep_time`, `arr_time`, `sched_arr_time` because they are all <dttm> (datetime).

### Exercise 2

Let's start a pipe with the `flights_dt` to `mutate()` our data. Set `weekday` to `wday(dep_time, label = TRUE)`.

```{r datetime-components-with-getti-2, exercise = TRUE}

```

```{r datetime-components-with-getti-2-hint-1, eval = FALSE}
... |> 
  mutate(weekday = ...)
```

### 

By setting the `label = TRUE` we can return the abbreviated name of the day of the week.

### Exercise 3

Now let's plot our data using `ggplot()` and within `aes()` set `x` to `weekday`.

```{r datetime-components-with-getti-3, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r datetime-components-with-getti-3-hint-1, eval = FALSE}
... |> 
 ... |> 
  ggplot(aes(x = ...))
```

### Exercise 4

Add `geom_bar()` to the pipe.

```{r datetime-components-with-getti-4, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r datetime-components-with-getti-4-hint-1, eval = FALSE}
... |> 
  ... |> 
  ... +
  geom_bar()
```

### 

We can use `wday()` to see that more flights depart during the week than on the weekend.

## Date and time components with rounding
### 

An alternative approach to plotting individual components is to round the date to a nearby unit of time, with `floor_date()`, `round_date()`, and `ceiling_date()`. Each function takes a vector of dates to adjust and then the name of the unit to round down (floor), round up (ceiling), or round to. 

### Exercise 1

Pipe `flights_dt` to `mutate()`. Set `dep_hour` to `dep_time - floor_date(dep_time, "day")`.

```{r date-and-time-components-with-1, exercise = TRUE}

```

```{r date-and-time-components-with-1-hint-1, eval = FALSE}
flights_dt |>
  mutate(dep_hour = ... - ...())
```

```{r date-and-time-components-with-1-test, include = FALSE}
flights_dt |>
  mutate(dep_hour = dep_time - floor_date(dep_time, "day"))
```

### 

Computing the difference between a pair of date-times yields a difftime. A difftime class object records a time span of seconds, minutes, hours, days, or weeks. This ambiguity can make difftimes a little painful to work with, so **lubridate** provides an alternative which always uses seconds: the duration.

### Exercise 2

DK: Do something better than just ignore the message.

Continue the pipe with `ggplot()`. Set `x` to `dep_hour` in `aes()`. Ignore the message about "Don't know how to automatically pick ..."

```{r date-and-time-components-with-2, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r date-and-time-components-with-2-hint-1, eval = FALSE}
... |>
  ... |>
  ggplot(aes(x = ...))
```

```{r date-and-time-components-with-2-test, include = FALSE}
flights_dt |>
  mutate(dep_hour = dep_time - floor_date(dep_time, "day")) |> 
  ggplot(aes(x = dep_hour))
```

### Exercise 3

Add `geom_freqpoly()` to the pipe to view the difference by setting `binwidth` to `60*30` in `geom_freqpoly()`.

```{r date-and-time-components-with-3, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r date-and-time-components-with-3-hint-1, eval = FALSE}
... |>
  ... |>
  ... +
    geom_freqpoly(binwidth = ...)
```

```{r date-and-time-components-with-3-test, include = FALSE}
flights_dt |>
  mutate(dep_hour = dep_time - floor_date(dep_time, "day")) |> 
  ggplot(aes(x = dep_hour)) +
    geom_freqpoly(binwidth = 60*30)
```

### 

You can use rounding to show the distribution of flights across the course of a day by computing the difference between `dep_time` and the earliest instant of that day

## Modifying date/time components
### 

You can also use each accessor function to modify the components of a date/time. This doesn’t come up much in data analysis, but can be useful when cleaning data that has clearly incorrect dates.

### Exercise 1

Let's modify this date: "2026-07-08 12:34:56" with the `ymd_hms()` function. Create a `datetime2026` variable and set `ymd_hms()` to this.

```{r modifying-date-time-components-1, exercise = TRUE}

```

```{r modifying-date-time-components-1-hint-1, eval = FALSE}
datetime2026 <- ymd_hms("...")
```

### Exercise 2

Let's modify the date by using `year()` on `datetime2026` and setting it to 2030. Type `datetime2026` after to see whether it has been changed.

```{r modifying-date-time-components-2, exercise = TRUE}

```

```{r modifying-date-time-components-2-hint-1, eval = FALSE}
year(...) <- 2030
datetime2026
```

### 

With the `ymd_hms()` functions we can automatically assign the Universal Coordinated Time Zone (UTC) to the parsed date.

### 

Alternatively, rather than modifying an existing variable, you can create a new date-time with update(). Check out [`update()`](https://lubridate.tidyverse.org/reference/DateTimeUpdate.html) for more information.

## Time Spans with Duration
### 

You’ll learn how arithmetic with dates works, including subtraction, addition, and division.

### Exercise 1

Set `today() - ymd("2000-8-30")` to the `age` variable.

```{r time-spans-with-duration-1, exercise = TRUE}

```

```{r time-spans-with-duration-1-hint-1, eval = FALSE}
... <- today() - ymd("2000-8-30")
```

### 

As we covered in the previous exercises, we use `ymd()` to create dates. 

### Exercise 2

Now type `age` and run it.

```{r time-spans-with-duration-2, exercise = TRUE}

```

```{r time-spans-with-duration-2-hint-1, eval = FALSE}
age
```

### 

Here we subtracted two dates to get a `difftime` object to get the time difference. A `difftime` class object records a time span of seconds, minutes, hours, days, or weeks. This ambiguity can make `difftimes` a little painful to work with, so lubridate provides an alternative which always uses seconds: the duration.

### Exercise 3

Run `as.duration()` on `age`.

```{r time-spans-with-duration-3, exercise = TRUE}

```

```{r time-spans-with-duration-3-hint-1, eval = FALSE}
as.duration(...)
```

### 

We use `as.duration()` to get the time difference of two dates in second and years. The **lubridate** alternative always provides durations in seconds.

### Exercise 4

Multiply the `as.duration()` from above by `2` and add `dweeks(12)`.

```{r time-spans-with-duration-4, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r time-spans-with-duration-4-hint-1, eval = FALSE}
... * 2 + dweeks(...)
```

### 

With durations, we can add, divide, subtract, and multiply with other functions to get a new desired output. With duration we can use `dseconds()` (seconds), `dminutes()` (minutes), `dhours()` (hours), `ddays()` (days), `dweeks()` (weeks), `dyears()` (years). Check out all of the other functions here: [**Duration**](https://lubridate.tidyverse.org/reference/duration.html)

## Time Spans with Periods
### 

Periods are time spans but don’t have a fixed length in seconds, instead they work with “human” times, like days and months.

### Exercise 1

Set `ymd_hms("2026-03-08 01:00:00", tz = "America/New_York")` to the `date2026` variable and run the variable to see the datetime.

```{r time-spans-with-periods-1, exercise = TRUE}

```

```{r time-spans-with-periods-1-hint-1, eval = FALSE}
... <- ymd_hms("2026-03-08 01:00:00", tz = "America/New_York")
date2026
```

### 

Unlike above where we specified `tz` as "EST" or "UTC". We can use "America/New_York" to specify that we are working in "EST".

### Exercise 2

Let's add `dweeks(3)` to `date2026`.

```{r time-spans-with-periods-2, exercise = TRUE}

```

```{r time-spans-with-periods-2-hint-1, eval = FALSE}
date2026 + ...
```

### 

Here we can see that our time zone changed and it changed into "EDT". To solve this problem, **lubridate** provides *periods*. 

### Exercise 3

Let's add 10 to `date2026`, multiply by `hours(20)` and subtract `months(5)`.

```{r time-spans-with-periods-3, exercise = TRUE}

```

```{r time-spans-with-periods-3-hint-1, eval = FALSE}
date2026 + ... * ... - ...
```

### 

Similar to durations, we can use periods to multiply, divide, subtract, and add dates together. However, with periods are more likely to do what you expect.

### Exercise 4

Add `dyears(2)` to `date2026`. On a separate line add `years(2)` to `date2026`.

```{r time-spans-with-periods-4, exercise = TRUE}

```

```{r time-spans-with-periods-4-hint-1, eval = FALSE}
... + dyears(...)
... + years(...)
```

### 

We can see here that `dyears()` failed to keep the same timezone. However, with `years()` we were able to keep the same timezone. With the help of periods, we can use time spans more accurately.

## Time Spans with Intervals
### 

An interval is a pair of starting and ending date times, or you can think of it as a duration with a starting point.

### Exercise 1

Let's create a `ymd()` date set to Jan 1st, 2021 and set it to `date2021`.

```{r time-spans-with-intervals-1, exercise = TRUE}

```

```{r time-spans-with-intervals-1-hint-1, eval = FALSE}
... <- ymd("2021-01-01")
```

### Exercise 2

Let's create a `ymd()` date set to Jan 1st, 2020 and set it to `date2020`.

```{r time-spans-with-intervals-2, exercise = TRUE}

```

```{r time-spans-with-intervals-2-hint-1, eval = FALSE}
date2020 <- ...("2020-01-01")
```

### Exercise 3

Now let's create an `interval` variable and set it to `date2020 %--% date2021`.

```{r time-spans-with-intervals-3, exercise = TRUE}

```

```{r time-spans-with-intervals-3-hint-1, eval = FALSE}
... <- date2020 %--% date2021
```

### 

We use the `%--%` to create a more accurate measurement, through the use of an interval. We have created an interval of a year specifically a leap year.

### Exercise 4

Divide the `interval` by `days(1)` and divide `years(1)` by `days(1)` on a separate line.

```{r time-spans-with-intervals-4, exercise = TRUE}

```

```{r time-spans-with-intervals-4-hint-1, eval = FALSE}
... / days(1)
years(1) / ...
```

### 

With the `years(1) / days(1)` we get an inaccurate estimate of 365.25 days in a year. With the use of an interval we are able to get an accurate estimate of the year.

### 

Whenever possible we attempt to use duration, periods, and interval respectively based on the situation because of the accuracy it provides us.

## Time Zones
### 

Time zones are an enormously complicated topic because of their interaction with geopolitical entities. Fortunately we don’t need to dig into all the details as they’re not all important for data analysis, but there are a few challenges we’ll need to tackle head on.

### Exercise 1

Type `Sys.timezone()` and run in the code chunk below.

```{r time-zones-1, exercise = TRUE}

```

```{r time-zones-1-hint-1, eval = FALSE}
...()
```

### 

We can find out what R thinks our current time zone is with `Sys.timezone()`.

### Exercise 2

Set `newyorkdate` to `ymd_hms()` for the date of Jun 20, 2023 12:00:00 in the "America/New_York" timezone.

```{r time-zones-2, exercise = TRUE}

```

```{r time-zones-2-hint-1, eval = FALSE}
newyorkdate <- ymd_hms(...)
```

```{r time-zones-2-hint-2, eval = FALSE}
... <- ymd_hms("2023-06-20 12:00:00", tz = ...)
```

### 

We are probably familiar with EST, or Eastern Standard Time. However, both Australia and Canada also have EST! To avoid confusion, R uses the international standard IANA time zones. These use a consistent naming scheme {area}/{location}, typically in the form {continent}/{city} or {ocean}/{city}.

### Exercise 3

Set `parisdate` to `ymd_hms()` for the date of Jun 20, 2023 18:00:00 in the "Europe/Paris" timezone.

```{r time-zones-3, exercise = TRUE}

```

```{r time-zones-3-hint-1, eval = FALSE}
... <- ymd_hms("2023-06-20 18:00:00", tz = ...)
```

### Exercise 4

Subtract `newyorkdate` from `parisdate`.

```{r time-zones-4, exercise = TRUE}

```

```{r time-zones-4-hint-1, eval = FALSE}
parisdate - ...
```

### 

We can verify that these are both in the same time zone by subtracting them. You might wonder why the time zone uses a city, when typically you think of time zones as associated with a country or region within a country. This is because the IANA database has to record decades worth of time zone rules. Read more about [**IANA**](https://www.iana.org/time-zones).

### Exercise 5

We can combine datetimes, as well with different timezones. Set `combined` to `c()`. Within `c()` include `parisdate` and `newyorkdate`. Run `combined` after to see the result.

```{r time-zones-5, exercise = TRUE}

```

```{r time-zones-5-hint-1, eval = FALSE}
combined <- c(..., ...)
```

### 

Operations that combine date-times, like `c()`, will often drop the time zone. In that case, the date-times will display in the time zone of the first element. Let's fix this issue in the next exercises.

### Exercise 6

We can change the timezone through `with_tz()`. In `with_tz()` use `combined` and set `tzone` to "Pacific/Auckland".


```{r time-zones-6, exercise = TRUE}

```

```{r time-zones-6-hint-1, eval = FALSE}
...(combined, tzone = ...)
```

### 

We use `with_tz()` when we want to keep the instant in time the same, and change how it’s displayed. Use this when the instant is correct, but want a more natural display.

### Exercise 7

We can also change the timezone through `force_tz()`. In `force_tz()` use `combined` and set `tzone` to "Pacific/Auckland".

```{r time-zones-7, exercise = TRUE}

```

```{r time-zones-7-hint-1, eval = FALSE}
force_tz(..., tzone = "Pacific/Auckland")
```

### 

When we want to change the underlying instant in time we use `force_tz()`. Use this when you have an instant that has been labelled with the incorrect time zone, and need to fix it.

## Summary
### 

This tutorial covered [Chapter 17: Dates and times](https://r4ds.hadley.nz/datetimes.html) from [*R for Data Science (2e)*](https://r4ds.hadley.nz/) by Hadley Wickham, Mine Çetinkaya-Rundel, and Garrett Grolemund. You learned how to use the [**lubridate**](https://lubridate.tidyverse.org/) on the `flights` data from the [**nyc13flights**](https://nycflights13.tidyverse.org/) package.

```{r download-answers, child = system.file("child_documents/download_answers.Rmd", package = "tutorial.helpers")}
```
