Skip to content

Commit

Permalink
add Ops.hms and tests for {+-*/} {integer,numeric} and {+-} Date
Browse files Browse the repository at this point in the history
  • Loading branch information
AshesITR committed Aug 21, 2023
1 parent c575574 commit 0f4a5ae
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
CRAN-RELEASE
docs
.vscode
.idea
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Generated by roxygen2: do not edit by hand

S3method("+",Date)
S3method("-",Date)
S3method("[<-",hms)
S3method("[[",hms)
S3method("units<-",hms)
S3method(Ops,hms)
S3method(as.POSIXct,hms)
S3method(as.POSIXlt,hms)
S3method(as.character,hms)
Expand Down
20 changes: 20 additions & 0 deletions R/generics.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#' @export
Ops.hms <- function(e1, e2) {
if (.Generic == "+" && (inherits(e1, "Date") || inherits(e2, "Date"))) {
return(base::`+.Date`(e1, e2))
} else if (.Generic == "-" && inherits(e1, "Date")) {
return(base::`-.Date`(e1, e2))
}
res <- NextMethod(.Generic)
if (inherits(res, "difftime")) {
as_hms(res)
} else {
res
}
}

#' @export
`+.Date` <- Ops.hms

#' @export
`-.Date` <- Ops.hms
65 changes: 65 additions & 0 deletions tests/testthat/test-generics.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
test_that("generic operations work as intended", {
# Test that all binary operations involving hms and one of Date, POSIXct, POSIXlt, difftime, hms, numeric, integer
# behave the same as the operation would with a difftime of the same length, except for difftime results, wich should
# be hms of the same value instead.

hms_test_vec <- new_hms(c(0.0, NA_real_, 10.0))

# hms {+-*/} integer
expect_equal(hms_test_vec + 1L, new_hms(c(1.0, NA_real_, 11.0)))
expect_equal(hms_test_vec + (1L:3L), new_hms(c(1.0, NA_real_, 13.0)))
expect_equal(1L + hms_test_vec, new_hms(c(1.0, NA_real_, 11.0)))
expect_equal((1L:3L) + hms_test_vec, new_hms(c(1.0, NA_real_, 13.0)))

expect_equal(hms_test_vec - 1L, new_hms(c(-1.0, NA_real_, 9.0)))
expect_equal(hms_test_vec - (1L:3L), new_hms(c(-1.0, NA_real_, 7.0)))
expect_equal(1L - hms_test_vec, new_hms(c(1.0, NA_real_, -9.0)))
expect_equal((1L:3L) - hms_test_vec, new_hms(c(1.0, NA_real_, -7.0)))

expect_equal(hms_test_vec * 2L, new_hms(c(0.0, NA_real_, 20.0)))
expect_equal(hms_test_vec * (1L:3L), new_hms(c(0.0, NA_real_, 30.0)))
expect_equal(2L * hms_test_vec, new_hms(c(0.0, NA_real_, 20.0)))
expect_equal((1L:3L) * hms_test_vec, new_hms(c(0.0, NA_real_, 30.0)))

expect_equal(hms_test_vec / 2L, new_hms(c(0.0, NA_real_, 5.0)))
expect_equal(hms_test_vec / c(1L, 2L, 4L), new_hms(c(0.0, NA_real_, 2.5)))
expect_error(1L / hms_test_vec, "second argument of / cannot be a \"difftime\" object")

# hms {+-*/} numeric
expect_equal(hms_test_vec + 1.0, new_hms(c(1.0, NA_real_, 11.0)))
expect_equal(hms_test_vec + (1.0:3.0), new_hms(c(1.0, NA_real_, 13.0)))
expect_equal(1.0 + hms_test_vec, new_hms(c(1.0, NA_real_, 11.0)))
expect_equal((1.0:3.0) + hms_test_vec, new_hms(c(1.0, NA_real_, 13.0)))

expect_equal(hms_test_vec - 1.0, new_hms(c(-1.0, NA_real_, 9.0)))
expect_equal(hms_test_vec - (1.0:3.0), new_hms(c(-1.0, NA_real_, 7.0)))
expect_equal(1.0 - hms_test_vec, new_hms(c(1.0, NA_real_, -9.0)))
expect_equal((1.0:3.0) - hms_test_vec, new_hms(c(1.0, NA_real_, -7.0)))

expect_equal(hms_test_vec * 2.0, new_hms(c(0.0, NA_real_, 20.0)))
expect_equal(hms_test_vec * (1.0:3.0), new_hms(c(0.0, NA_real_, 30.0)))
expect_equal(2.0 * hms_test_vec, new_hms(c(0.0, NA_real_, 20.0)))
expect_equal((1.0:3.0) * hms_test_vec, new_hms(c(0.0, NA_real_, 30.0)))

expect_equal(hms_test_vec / 2.0, new_hms(c(0.0, NA_real_, 5.0)))
expect_equal(hms_test_vec / c(1.0, 2.0, 4.0), new_hms(c(0.0, NA_real_, 2.5)))
expect_error(1.0 / hms_test_vec, "second argument of / cannot be a \"difftime\" object")

# hms {+-} Date
# 86400.0 secs = 24 hours
hms_test_vec <- new_hms(86400.0 * c(1.0, NA_real_, 10.0))
difftime_test_vec <- as.difftime(86400.0 * c(1.0, NA_real_, 10.0), units = "secs")
date_vec <- as.Date(c("1970-01-01", NA_character_, "2023-08-21"))

expect_equal(hms_test_vec + date_vec, difftime_test_vec + date_vec)
expect_equal(date_vec + hms_test_vec, date_vec + difftime_test_vec)

# Can't reproduce this warning because we forced compatibility
hms_result <- hms_test_vec - date_vec
expect_warning({
difftime_result <- as_hms(difftime_test_vec - date_vec)
}, regexp = "Incompatible methods \\(\"Ops.difftime\", \"-.Date\") for \"-\"")
expect_equal(hms_result, difftime_result)

expect_equal(date_vec - hms_test_vec, date_vec - difftime_test_vec)
})

0 comments on commit 0f4a5ae

Please sign in to comment.