'R - Get Daylight Saving Beginning and Ending from year

My question is fairly simple, yet I didn't really find an answer for it.

I want to write a function like so:

get_dst <- function(y = 2019){

}

y is the year input of the function

the ouput should be a list or a vector of datetimes that represent European Daylight Saving Times start and end.

For 2019 the output would be:

31-03-2019 02:00:00, 27-10-2019 03:00:00

for 2020 the output would be:

29-03-2020 02:00:00, 25-10-2019 03:00:00

Also I think dplyr should have a way to handle them when grouping on a variable that is a datetime because it is hard to work with them.



Solution 1:[1]

Within the function, we could create a sequence and apply dst to return TRUE/FALSE, subset and get the range

get_dst <- function(y = 2019, tz){
         start <- paste0(y, '-01-01')
         end <- paste0(y, '-12-31')
         d1 <- seq(as.POSIXct(start, tz = tz),
              as.POSIXct(end, tz =tz), by = 'hour')
         range(d1[lubridate::dst(d1)])
  }

get_dst(2019,  "America/New_York")

Solution 2:[2]

The clock package actually exposes a way to get the previous/next daylight saving time boundary given a particular time point through sys_time_info(). We can use this to get all of the DST boundaries in a particular year.

library(clock)

dst_boundaries <- function(year, zone) {
  # [start, end)
  # example: [2021-01-01, 2022-01-01)
  start <- date_time_build(year, zone = zone)
  end <- date_time_build(year + 1L, zone = zone)
  
  start <- as_sys_time(start)
  end <- as_sys_time(end)
  
  # An empty vector of date-times that we will add boundaries to
  boundaries <- .POSIXct(double(), tz = zone)
  
  repeat {
    # Look up DST info based on the current `start`.
    # It'll find the previous and next DST boundary.
    info <- sys_time_info(start, zone)
    boundary <- info$end
    
    # Is the DST boundary outside this year? If so, we are done.
    if (boundary >= end) {
      break
    }
    
    # Otherwise add it to our growing list of boundaries
    boundaries <- c(boundaries, as.POSIXct(boundary, tz = zone))
    start <- boundary
  }
  
  boundaries
}

dst_boundaries(2019, "America/New_York")
#> [1] "2019-03-10 03:00:00 EDT" "2019-11-03 01:00:00 EST"

# Apia, Samoa stopped using DST halfway through 2021
dst_boundaries(2020, "Pacific/Apia")
#> [1] "2020-04-05 03:00:00 +13" "2020-09-27 04:00:00 +14"
dst_boundaries(2021, "Pacific/Apia")
#> [1] "2021-04-04 03:00:00 +13"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Davis Vaughan