Skip to content

Commit

Permalink
Change 'shorter_interval()' to output only 'Interval' objects
Browse files Browse the repository at this point in the history
  • Loading branch information
danielvartan committed Oct 4, 2021
1 parent 45a1c7b commit 7fac8b2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 104 deletions.
101 changes: 39 additions & 62 deletions R/shorter_interval.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
#'
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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))

Expand All @@ -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)
}
2 changes: 1 addition & 1 deletion R/utils.R
Original file line number Diff line number Diff line change
@@ -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())

Expand Down
67 changes: 26 additions & 41 deletions man/shorter_interval.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7fac8b2

Please sign in to comment.