Skip to content

Commit

Permalink
add {+-}.POSIXt and tests for {+-} POSIXct
Browse files Browse the repository at this point in the history
  • Loading branch information
AshesITR committed Aug 22, 2023
1 parent 0f4a5ae commit 32c65fe
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 15 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Generated by roxygen2: do not edit by hand

S3method("+",Date)
S3method("+",POSIXt)
S3method("-",Date)
S3method("-",POSIXt)
S3method("[<-",hms)
S3method("[[",hms)
S3method("units<-",hms)
Expand Down
14 changes: 14 additions & 0 deletions R/generics.R
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
#' @export
Ops.hms <- function(e1, e2) {
# This logic is hard-coded in R for difftime
# cf. https://github.com/wch/r-source/blob/a46559e8f728317da979be60e401899ae60086b2/src/main/eval.c#L3406-L3419
if (.Generic == "+" && (inherits(e1, "Date") || inherits(e2, "Date"))) {
return(base::`+.Date`(e1, e2))
} else if (.Generic == "-" && inherits(e1, "Date")) {
return(base::`-.Date`(e1, e2))
} else if (.Generic == "+" && (inherits(e1, "POSIXt") || inherits(e2, "POSIXt"))) {
return(base::`+.POSIXt`(e1, e2))
} else if (.Generic == "-" && inherits(e1, "POSIXt")) {
return(base::`-.POSIXt`(e1, e2))
}

# delegate to Ops.difftime
res <- NextMethod(.Generic)
if (inherits(res, "difftime")) {
as_hms(res)
Expand All @@ -18,3 +26,9 @@ Ops.hms <- function(e1, e2) {

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

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

#' @export
`-.POSIXt` <- Ops.hms
6 changes: 0 additions & 6 deletions tests/testthat/helper-compare.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,3 @@ expect_hms_equal <- function(x, y) {
expect_s3_class(y, "hms")
expect_equal(as.numeric(x), as.numeric(y))
}

expect_difftime_equal <- function(x, y) {
expect_s3_class(x, "difftime")
expect_s3_class(y, "difftime")
expect_equal(as.numeric(as_hms(x)), as.numeric(as_hms(y)))
}
10 changes: 5 additions & 5 deletions tests/testthat/test-arith.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ test_that("arithmetics work", {
expect_equal(hms(days = 1) + as.Date("2016-03-31"), as.Date("2016-04-01"))
expect_equal(empty_tz(hms(hours = 1) + as.POSIXct("2016-03-31")), as.POSIXct("2016-03-31 01:00:00"))

expect_difftime_equal(hms(1) + hms(2), hms(3))
expect_difftime_equal(hms(1) - hms(2), hms(-1))
expect_difftime_equal(2 * hms(1), hms(2))
expect_difftime_equal(hms(hours = 1) / 2, hms(minutes = 30))
expect_difftime_equal(-hms(1), hms(-1))
expect_hms_equal(hms(1) + hms(2), hms(3))
expect_hms_equal(hms(1) - hms(2), hms(-1))
expect_hms_equal(2 * hms(1), hms(2))
expect_hms_equal(hms(hours = 1) / 2, hms(minutes = 30))
expect_hms_equal(-hms(1), hms(-1))
})

test_that("component extraction work", {
Expand Down
50 changes: 46 additions & 4 deletions tests/testthat/test-generics.R
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,52 @@ test_that("generic operations work as intended", {

# 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_warning(
difftime_result <- as_hms(difftime_test_vec - date_vec),
regexp = "Incompatible methods \\(\"Ops.difftime\", \"-.Date\") for \"-\""
)
expect_equal(hms_result, difftime_result, info = "hms - Date not equal to difftime - Date")

expect_equal(date_vec - hms_test_vec, date_vec - difftime_test_vec)

# hms {+-} POSIXt
posixct_vec <- as.POSIXct(
c("2023-03-26 03:00:00", "2023-10-29 02:00:00", NA_character_, "1970-01-01 00:00:00"),
tz = "Europe/Berlin"
)

posix_difftime_result <- posixct_vec + as.difftime(1.0, units = "hours")
expect_equal(
format(posix_difftime_result, usetz = TRUE),
c("2023-03-26 04:00:00 CEST", "2023-10-29 02:00:00 CET", NA_character_, "1970-01-01 01:00:00 CET")
)
expect_equal(posixct_vec + hms(hours = 1L), posix_difftime_result)
expect_equal(hms(hours = 1L) + posixct_vec, posix_difftime_result)
expect_equal(as.difftime(1.0, units = "hours") + posixct_vec, posix_difftime_result)

posix_difftime_result <- posixct_vec - as.difftime(1.0, units = "hours")
expect_equal(
format(posix_difftime_result, usetz = TRUE),
c("2023-03-26 01:00:00 CET", "2023-10-29 01:00:00 CEST", NA, "1969-12-31 23:00:00 CET"),
info = "POSIXct - difftime"
)
expect_equal(posixct_vec - hms(hours = 1L), posix_difftime_result)

hms_result <- hms(hours = 1L) - posixct_vec
expect_warning(
difftime_result <- as.difftime(3600.0, units = "secs") - posixct_vec,
regexp = "Incompatible methods \\(\"Ops.difftime\", \"-.POSIXt\") for \"-\""
)
# FIXME this currently returns a different result than difftime - POSIXt.
# hms - POSIXt produces a hms
# difftime - POSIXt produces a POSIXt
expect_equal(
as.numeric(hms_result), as.numeric(difftime_result),
info = "hms - POSIXt not equal to difftime - POSIXt"
)
expect_hms_equal(hms_result, new_hms(c(-1679788800.0, -1698534000.0, NA_real_, 7200.0)))
expect_equal(
difftime_result,
as.POSIXct(c(-1679788800.0, -1698534000.0, NA_real_, 7200.0), origin = "1970-01-01", tz = "Europe/Berlin")
)
})

0 comments on commit 32c65fe

Please sign in to comment.