R/get-forecast-for.r

Defines functions get_forecast_for

Documented in get_forecast_for

#' Retrieve weather data for a specific place/time
#'
#' Query for a specific time, past or future (for many places, 60 years in the past to 10
#' years in the future).
#'
#' If you wish to have results in something besides Imperial units, set \code{units} to
#' one of (\code{si}, \code{ca}, \code{uk}). Setting \code{units} to \code{auto} will have
#' the API select the relevant units automatically, based on geographic location. This
#' value is set to \code{us} (Imperial) units by default.
#'
#' If you wish to have text summaries presented in a different language, set
#' \code{language} to one of (\code{ar}, \code{bs}, \code{de}, \code{es}, \code{fr},
#' \code{it}, \code{nl}, \code{pl}, \code{pt}, \code{ru}, \code{sv}, \code{tet},
#' \code{tr}, \code{x-pig-latin}, \code{zh}). This value is set to \code{en} (English) by
#' default.
#'
#' See the Options section of the official
#' \href{https://darksky.net/dev/docs}{Forecast API documentation} for more
#' information.
#'
#' @param latitude forecast latitude (character, decimal format)
#' @param longitude forecast longitude (character, decimal format)
#' @param timestamp should either be a UNIX time (that is, seconds since midnight GMT on 1
#'   Jan 1970) or a string formatted as follows: \code{[YYYY]-[MM]-[DD]T[HH]:[MM]:[SS]}
#'   (with an optional time zone formatted as \code{Z} for GMT time or
#'   \code{[+|-][HH][MM]} for an offset in hours or minutes). For the latter format, if no
#'   timezone is present, local time (at the provided latitude and longitude) is assumed.
#'   (This string format is a subset of ISO 8601 time. An as example,
#'   \code{2013-05-06T12:00:00-0400}.)
#' @param units return the API response in units other than the default Imperial unit
#' @param language return text summaries in the desired language
#' @param exclude exclude some number of data blocks from the API response. This is useful
#'   for reducing latency and saving cache space. This should be a comma-separated string
#'   (without spaces) including one or more of the following: (\code{currently},
#'   \code{minutely}, \code{hourly}, \code{daily}, \code{alerts}, \code{flags}). Crafting
#'   a request with all of the above blocks excluded is exceedingly silly and not
#'   recommended. Setting this parameter to \code{NULL} (the default) does not exclude any
#'   parameters from the results.
#' @param add_headers add the return headers to the object?
#' @param add_json add the raw JSON response to the object?
#' @param ... pass through parameters to \code{httr::GET} (e.g. to configure ssl options
#'   or proxies)
#' @return an \code{rforecastio} object that contains the original JSON response object (optionally), a
#'   list of  named `tbl_df` `data.frame` objects corresponding to what was returned by
#'   the API and (optionally) relevant response headers (\code{cache-control}, \code{expires},
#'   \code{x-forecast-api-calls}, \code{x-response-time}).
#' @export
#' @examples
#' tmp <- get_forecast_for(37.8267,-122.423, "2013-05-06T12:00:00-0400")
get_forecast_for <- function(latitude, longitude, timestamp,
                             units="us", language="en", exclude=NULL,
                             add_json=FALSE, add_headers=FALSE,
                             ...) {

  url <- sprintf("https://api.darksky.net/forecast/%s/%s,%s,%s",
                 forecastio_api_key(), latitude, longitude, timestamp)

  params <- list(units=units, lang=language)

  if (!is.null(exclude)) params$exclude <- exclude

  resp <- httr::GET(url=url, query=params, ...)
  httr::stop_for_status(resp)

  tmp <- httr::content(resp, as="parsed")

  lys <- c("hourly", "minutely", "daily")

  # hourly, minutely and daily blocks might not be in the response
  # so only process the ones that are actually in the response

  lapply(lys[which(lys %in% names(tmp))], function(x) {

    dat <- dplyr::bind_rows(lapply(tmp[[x]]$data, as_data_frame))

    # various time fields might not be in the block data, so only
    # process which ones are in the block data

    ftimes <- c("time", "sunriseTime", "sunsetTime", "temperatureMinTime",
                "temperatureMaxTime", "apparentTemperatureMinTime",
                "apparentTemperatureMaxTime", "precipIntensityMaxTime")

    # convert times to POSIXct since they make sense in tbl_dfs/data.frames

    ly <- dplyr::mutate_each_(dat, funs(convert_time),
                              vars=ftimes[which(ftimes %in% colnames(dat))])

  }) -> fio_data

  fio_data <- setNames(fio_data, lys[which(lys %in% names(tmp))])

  # add currently as a data frame to the return list since that's helpful for
  # rbinding later for folks

  if ("currently" %in% names(tmp)) {
    currently <- dplyr::as_data_frame(tmp$currently)
    if ("time" %in% colnames(currently)) {
      currently <- dplyr::mutate(currently, time=convert_time(time))
    }
    fio_data$currently <- currently
  }

  if (add_json) fio_data$json <- tmp

  ret_val <- fio_data

  if (add_headers) {
    dev_heads <- c("cache-control", "expires", "x-forecast-api-calls", "x-response-time")
    ret_heads <- httr::headers(resp)

    ret_val <- c(fio_data, ret_heads[dev_heads[which(dev_heads %in% names(ret_heads))]])
  }

  class(ret_val) <- c("rforecastio", class(ret_val))
  return(ret_val)

}
hrbrmstr/Rforecastio documentation built on May 17, 2019, 4:55 p.m.