From 7fac8b22730337187c56d49fa3f10b5811843cbd Mon Sep 17 00:00:00 2001 From: Daniel Vartanian Date: Sun, 3 Oct 2021 23:18:43 -0300 Subject: [PATCH] Change 'shorter_interval()' to output only 'Interval' objects --- R/shorter_interval.R | 101 ++++++++++++++++------------------------ R/utils.R | 2 +- man/shorter_interval.Rd | 67 +++++++++++--------------- 3 files changed, 66 insertions(+), 104 deletions(-) diff --git a/R/shorter_interval.R b/R/shorter_interval.R index 2563ec7..3d45745 100644 --- a/R/shorter_interval.R +++ b/R/shorter_interval.R @@ -9,7 +9,7 @@ #' #' `longer_interval()` do the inverse of `shorter_interval()`, i.e., #' finds the longer interval between two hours. It's just a wrapper for -#' `shorter_interval(x, y, class, inverse = TRUE)`. +#' `shorter_interval(x, y, inverse = TRUE)`. #' #' @details #' @@ -65,6 +65,15 @@ #' 12h 12h 12h #' ``` #' +#' ## Base date and timezone +#' +#' `shorter_interval()` uses the +#' [Unix epoch](https://en.wikipedia.org/wiki/Unix_time) (1970-01-01) date as +#' the start date for creating intervals. +#' +#' The output will always have `"UTC"` set as timezone. Learn more about +#' time zones in [base::timezone]. +#' #' ## Class requirements #' #' The `mctq` package works with a set of object classes specially created to @@ -73,33 +82,24 @@ #' conform to the object classes required, you can use the `mctq` #' [mctq::convert()] function to convert it. #' -#' ## `class` argument -#' -#' `shorter_interval()` is integrated with [mctq::convert()]. That way you -#' can choose what class of object you prefer as output. -#' -#' Valid `class` values are: `"Duration"`, `"Period"`, `"difftime"`, `"hms"`, -#' and `"Interval"` (case insensitive). -#' #' ## `POSIXt` objects #' #' `POSIXt` objects passed as argument to `x` or `y` will be stripped of their #' dates. Only the time will be considered. #' +#' Both `POSIXct` and `POSIXlt` are objects that inherits the class `POSIXt`. +#' Learn more about it in [base::DateTimeClasses]. +#' #' @param x,y A `hms` or `POSIXt` object. -#' @param class (optional) a string indicating the object class of the output -#' (default: `"hms"`). #' @param inverse (optional) a `logical` value indicating if the function must #' return an inverse output, i.e., the longer interval between `x` and `y`. -#' @param quiet (optional) a `logical` value indicating if warnings or messages -#' must be suppressed (default: `FALSE`). #' #' @return #' -#' * If `inverse = FALSE` (default), an object of the indicated class in -#' `class` (default: `"hms"`) with the shorter interval between `x` and `y`. -#' * If `inverse = TRUE`, an object of the indicated class in `class` (default: -#' `"hms"`) with the longer interval between `x` and `y`. +#' * If `inverse = FALSE` (default), an `Interval` object with the shorter +#' interval between `x` and `y`. +#' * If `inverse = TRUE`, an `Interval` object with the longer interval between +#' `x` and `y`. #' #' @family utility functions #' @export @@ -110,61 +110,42 @@ #' x <- hms::parse_hm("23:00") #' y <- hms::parse_hm("01:00") #' shorter_interval(x, y) -#' #> 02:00:00 # Expected +#' #> [1] 1970-01-01 23:00:00 UTC--1970-01-02 01:00:00 UTC # Expected #' #' x <- lubridate::as_datetime("1985-01-15 12:00:00") #' y <- lubridate::as_datetime("2020-09-10 12:00:00") #' shorter_interval(x, y) -#' #> 00:00:00 # Expected +#' #> [1] 1970-01-01 12:00:00 UTC--1970-01-01 12:00:00 UTC # Expected #' #' ## Vector example #' #' x <- c(hms::parse_hm("15:30"), hms::parse_hm("21:30")) #' y <- c(hms::parse_hm("19:30"), hms::parse_hm("04:00")) #' shorter_interval(x, y) -#' #> 04:00:00 # Expected -#' #> 06:30:00 # Expected +#' #> [1] 1970-01-01 15:30:00 UTC--1970-01-01 19:30:00 UTC # Expected +#' #> [2] 1970-01-01 21:30:00 UTC--1970-01-02 04:00:00 UTC # Expected #' #' ## Finding the longer interval between two hours #' #' x <- lubridate::parse_date_time("01:10:00", "HMS") #' y <- lubridate::parse_date_time("11:45:00", "HMS") #' shorter_interval(x, y, inverse = TRUE) -#' #> 13:25:00 # Expected +#' #> [1] 1970-01-01 11:45:00 UTC--1970-01-02 01:10:00 UTC # Expected #' #' x <- lubridate::as_datetime("1915-02-14 05:00:00") #' y <- lubridate::as_datetime("1970-07-01 05:00:00") #' longer_interval(x, y) -#' #> 24:00:00 # Expected -#' -#' ## Changing the output object class -#' -#' x <- as.POSIXct("1988-10-05 02:00:00") -#' y <- as.POSIXlt("2100-05-07 13:30:00") -#' shorter_interval(x, y, "Interval") -#' #> [1] 1970-01-01 02:00:00 UTC--1970-01-01 13:30:00 UTC # Expected -#' longer_interval(x, y, "Duration") -#' #> [1] "45000s (~12.5 hours)" # Expected -#' shorter_interval(x, y, "Period") -#' #> [1] "11H 30M 0S" # Expected -#' longer_interval(x, y, "hms") -#' #> 12:30:00" # Expected -shorter_interval <- function(x, y, class = "hms", inverse = FALSE, - quiet = FALSE) { - choices <- c("Duration", "Period", "difftime", "hms", "Interval") - - checkmate::assert_multi_class(x, c("hms", "POSIXct", "POSIXlt")) - checkmate::assert_multi_class(y, c("hms", "POSIXct", "POSIXlt")) +#' #> [1] 1970-01-01 05:00:00 UTC--1970-01-02 05:00:00 UTC # Expected +shorter_interval <- function(x, y, inverse = FALSE) { + checkmate::assert_multi_class(x, c("hms", "POSIXt")) + checkmate::assert_multi_class(y, c("hms", "POSIXt")) assert_identical(x, y, type = "length") checkmate::assert_numeric(as.numeric(hms::as_hms(x)), lower = 0, upper = 86400) checkmate::assert_numeric(as.numeric(hms::as_hms(y)), lower = 0, upper = 86400) - checkmate::assert_choice(tolower(class), tolower(choices)) checkmate::assert_flag(inverse) - class <- tolower(class) - x <- flat_posixt(convert(x, "posixct", quiet = TRUE)) y <- flat_posixt(convert(y, "posixct", quiet = TRUE)) @@ -189,27 +170,23 @@ shorter_interval <- function(x, y, class = "hms", inverse = FALSE, ) } - if (class == "interval") { - if (any(x1_y1_interval == y1_x2_interval, na.rm = TRUE)) { - flags <- which(x1_y1_interval == y1_x2_interval) + if (any(x1_y1_interval == y1_x2_interval, na.rm = TRUE)) { + flags <- which(x1_y1_interval == y1_x2_interval) - shush(cli::cli_alert_warning(paste0( - "Element(s) ", inline_collapse(flags), " of 'x' ", - "and 'y' have intervals equal to 12 hours, i.e., ", - "there's no shorter or longer interval ", - "between the two hours (they are equal). Only one ", - "possible interval was returned." - )), quiet = quiet) - } - - out - } else { - convert(out, class, quiet = TRUE) + cli::cli_alert_warning(paste0( + "Element{?s} {single_quote_(as.character(flags))} of 'x' ", + "and 'y' have intervals equal to 12 hours, i.e., ", + "there's no shorter or longer interval ", + "between the two hours (they are equal). Only one ", + "possible interval was returned." + )) } + + out } #' @rdname shorter_interval #' @export -longer_interval <- function(x, y, class = "hms", quiet = FALSE) { - shorter_interval(x, y, class, inverse = TRUE, quiet = quiet) +longer_interval <- function(x, y) { + shorter_interval(x, y, inverse = TRUE) } diff --git a/R/utils.R b/R/utils.R index 05028a7..eb8ad83 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,7 +1,7 @@ flat_posixt <- function(posixt, base = as.Date("1970-01-01"), force_tz = TRUE, tz = "UTC") { assert_posixt(posixt, null.ok = FALSE) - checkmate::assert_date(base, min.len = 1, max.len = 1) + checkmate::assert_date(base, len = 1, all.missing = FALSE) checkmate::assert_flag(force_tz) checkmate::assert_choice(tz, OlsonNames()) diff --git a/man/shorter_interval.Rd b/man/shorter_interval.Rd index d8a01e9..5b8ddf7 100644 --- a/man/shorter_interval.Rd +++ b/man/shorter_interval.Rd @@ -5,28 +5,22 @@ \alias{longer_interval} \title{Find the shorter interval between two hours} \usage{ -shorter_interval(x, y, class = "hms", inverse = FALSE, quiet = FALSE) +shorter_interval(x, y, inverse = FALSE) -longer_interval(x, y, class = "hms", quiet = FALSE) +longer_interval(x, y) } \arguments{ \item{x, y}{A \code{hms} or \code{POSIXt} object.} -\item{class}{(optional) a string indicating the object class of the output -(default: \code{"hms"}).} - \item{inverse}{(optional) a \code{logical} value indicating if the function must return an inverse output, i.e., the longer interval between \code{x} and \code{y}.} - -\item{quiet}{(optional) a \code{logical} value indicating if warnings or messages -must be suppressed (default: \code{FALSE}).} } \value{ \itemize{ -\item If \code{inverse = FALSE} (default), an object of the indicated class in -\code{class} (default: \code{"hms"}) with the shorter interval between \code{x} and \code{y}. -\item If \code{inverse = TRUE}, an object of the indicated class in \code{class} (default: -\code{"hms"}) with the longer interval between \code{x} and \code{y}. +\item If \code{inverse = FALSE} (default), an \code{Interval} object with the shorter +interval between \code{x} and \code{y}. +\item If \code{inverse = TRUE}, an \code{Interval} object with the longer interval between +\code{x} and \code{y}. } } \description{ @@ -37,7 +31,7 @@ must be suppressed (default: \code{FALSE}).} \code{longer_interval()} do the inverse of \code{shorter_interval()}, i.e., finds the longer interval between two hours. It's just a wrapper for -\code{shorter_interval(x, y, class, inverse = TRUE)}. +\code{shorter_interval(x, y, inverse = TRUE)}. } \details{ \subsection{The two intervals problem}{ @@ -90,6 +84,16 @@ shorter or longer interval (they will have equal length). In those cases, } } +\subsection{Base date and timezone}{ + +\code{shorter_interval()} uses the +\href{https://en.wikipedia.org/wiki/Unix_time}{Unix epoch} (1970-01-01) date as +the start date for creating intervals. + +The output will always have \code{"UTC"} set as timezone. Learn more about +time zones in \link[base:timezones]{base::timezone}. +} + \subsection{Class requirements}{ The \code{mctq} package works with a set of object classes specially created to @@ -99,19 +103,13 @@ conform to the object classes required, you can use the \code{mctq} \code{\link[=convert]{convert()}} function to convert it. } -\subsection{\code{class} argument}{ - -\code{shorter_interval()} is integrated with \code{\link[=convert]{convert()}}. That way you -can choose what class of object you prefer as output. - -Valid \code{class} values are: \code{"Duration"}, \code{"Period"}, \code{"difftime"}, \code{"hms"}, -and \code{"Interval"} (case insensitive). -} - \subsection{\code{POSIXt} objects}{ \code{POSIXt} objects passed as argument to \code{x} or \code{y} will be stripped of their dates. Only the time will be considered. + +Both \code{POSIXct} and \code{POSIXlt} are objects that inherits the class \code{POSIXt}. +Learn more about it in \link[base:DateTimeClasses]{base::DateTimeClasses}. } } \examples{ @@ -120,45 +118,32 @@ dates. Only the time will be considered. x <- hms::parse_hm("23:00") y <- hms::parse_hm("01:00") shorter_interval(x, y) -#> 02:00:00 # Expected +#> [1] 1970-01-01 23:00:00 UTC--1970-01-02 01:00:00 UTC # Expected x <- lubridate::as_datetime("1985-01-15 12:00:00") y <- lubridate::as_datetime("2020-09-10 12:00:00") shorter_interval(x, y) -#> 00:00:00 # Expected +#> [1] 1970-01-01 12:00:00 UTC--1970-01-01 12:00:00 UTC # Expected ## Vector example x <- c(hms::parse_hm("15:30"), hms::parse_hm("21:30")) y <- c(hms::parse_hm("19:30"), hms::parse_hm("04:00")) shorter_interval(x, y) -#> 04:00:00 # Expected -#> 06:30:00 # Expected +#> [1] 1970-01-01 15:30:00 UTC--1970-01-01 19:30:00 UTC # Expected +#> [2] 1970-01-01 21:30:00 UTC--1970-01-02 04:00:00 UTC # Expected ## Finding the longer interval between two hours x <- lubridate::parse_date_time("01:10:00", "HMS") y <- lubridate::parse_date_time("11:45:00", "HMS") shorter_interval(x, y, inverse = TRUE) -#> 13:25:00 # Expected +#> [1] 1970-01-01 11:45:00 UTC--1970-01-02 01:10:00 UTC # Expected x <- lubridate::as_datetime("1915-02-14 05:00:00") y <- lubridate::as_datetime("1970-07-01 05:00:00") longer_interval(x, y) -#> 24:00:00 # Expected - -## Changing the output object class - -x <- as.POSIXct("1988-10-05 02:00:00") -y <- as.POSIXlt("2100-05-07 13:30:00") -shorter_interval(x, y, "Interval") -#> [1] 1970-01-01 02:00:00 UTC--1970-01-01 13:30:00 UTC # Expected -longer_interval(x, y, "Duration") -#> [1] "45000s (~12.5 hours)" # Expected -shorter_interval(x, y, "Period") -#> [1] "11H 30M 0S" # Expected -longer_interval(x, y, "hms") -#> 12:30:00" # Expected +#> [1] 1970-01-01 05:00:00 UTC--1970-01-02 05:00:00 UTC # Expected } \seealso{ Other utility functions: