diff --git a/.ci/atime/tests.R b/.ci/atime/tests.R index d8fad8cc2..f1c5e017e 100644 --- a/.ci/atime/tests.R +++ b/.ci/atime/tests.R @@ -421,14 +421,17 @@ test.list <- atime::atime_test_list( expr = { ns = environment(data.table::as.IDate) s3_table = get(".__S3MethodsTable__.", envir = baseenv()) - if (exists("chooseOpsMethod.IDate", envir = s3_table)) { - rm("chooseOpsMethod.IDate", envir = s3_table) - } - if (exists("chooseOpsMethod.IDate", envir = ns, inherits = FALSE)) { - base::registerS3method( - "chooseOpsMethod", "IDate", - get("chooseOpsMethod.IDate", envir = ns), - envir = ns) + s3_generics = c("chooseOpsMethod.IDate" = "chooseOpsMethod", "-.IDate" = "-") + for (s3_method in names(s3_generics)) { + if (exists(s3_method, envir = s3_table, inherits = FALSE)) { + rm(list = s3_method, envir = s3_table) + } + if (exists(s3_method, envir = ns, inherits = FALSE)) { + base::registerS3method( + s3_generics[[s3_method]], "IDate", + get(s3_method, envir = ns, inherits = FALSE), + envir = ns) + } } outer(short_date, data.table::as.IDate(long_date), `-`) }), diff --git a/NEWS.md b/NEWS.md index 025e9a578..6693cee54 100644 --- a/NEWS.md +++ b/NEWS.md @@ -62,6 +62,8 @@ 13. `rbindlist()` (and therefore the `rbind()` method for `data.table`s) no longer raises an error upon encountering more than approximately 50000 columns in a list entry, [#7793](https://github.com/Rdatatable/data.table/issues/7793). The bug was introduced in `data.table` version 1.18.2.1. Thanks to @rickhelmus for the report and @aitap for the fix. +14. Subtracting an `IDate` from a `Date` is fast again by avoiding unnecessary conversion to `POSIXlt`/`POSIXct`, [#7825](https://github.com/Rdatatable/data.table/issues/7825). Thanks @gilesheywood for the report and @ben-schwen for the fix. + ### Notes 1. {data.table} now depends on R 3.5.0 (2018). diff --git a/R/IDateTime.R b/R/IDateTime.R index 99e6f64b2..7f2192671 100644 --- a/R/IDateTime.R +++ b/R/IDateTime.R @@ -111,7 +111,14 @@ chooseOpsMethod.IDate = function(x, y, mx, my, cl, reverse) inherits(y, "Date") `-.IDate` = function(e1, e2) { if (!inherits(e1, "IDate")) { - if (inherits(e1, 'Date')) return(base::`-.Date`(e1, e2)) + if (inherits(e1, "Date")) { + if (!inherits(e2, "Date")) return(base::`-.Date`(e1, e2)) + #7825 avoid base::`-.Date` to avoid conversion from IDate to POSIXlt/POSIXct + ans = unclass(e1) - unclass(e2) + setattr(ans, "class", "difftime") + setattr(ans, "units", "days") + return(ans) + } stopf("can only subtract from \"IDate\" objects") } if (storage.mode(e1) != "integer")