diff --git a/NAMESPACE b/NAMESPACE index dbc4aa28e9..ca4c74d9d9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -206,6 +206,8 @@ S3method(rep, IDate) S3method(rep, ITime) S3method(round, IDate) S3method(round, ITime) +S3method(is.numeric, IDate) +S3method(is.numeric, ITime) S3method(trunc, ITime) S3method(seq, IDate) S3method(seq, ITime) diff --git a/NEWS.md b/NEWS.md index 6693cee54d..acbbeca35b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,8 @@ 3. options `"datatable.old.matrix.autoname"` is now `FALSE` by default, meaning `names(data.table(x=1, cbind(1)))` is now `c("x", "V2")`. Toggle the option to retain the old behavior for now; future releases will work to remove this possibility. See the release notes for 1.18.0, item 1 under `NOTE OF INTENDED FUTURE POTENTIAL BREAKING CHANGES`. +4. `is.numeric()` now returns `FALSE` for `IDate` and `ITime`, since these classes don't support arbitrary numeric operations, [#7746](https://github.com/Rdatatable/data.table/issues/7746). Thanks @aitap for the report and fix. + ### NEW FEATURES 1. `nafill()`, `setnafill()` extended to work on logical, factor and character vectors (part of [#3992](https://github.com/Rdatatable/data.table/issues/3992)). Includes support for `Date`, `IDate`, `POSIXct` and character vectors. Thanks @jangorecki for the request and @jangorecki, @MichaelChirico and @ben-schwen for the PRs. diff --git a/R/IDateTime.R b/R/IDateTime.R index 7f21926714..931a518240 100644 --- a/R/IDateTime.R +++ b/R/IDateTime.R @@ -51,6 +51,10 @@ as.Date.IDate = function(x, ...) { } mean.IDate = + function(x, ...) { + x = unclass(x) + as.IDate(NextMethod()) + } seq.IDate = c.IDate = cut.IDate = @@ -90,6 +94,8 @@ round.IDate = function(x, digits=c("weeks", "months", "quarters", "years"), ...) quarters = ISOdate(year(x), 3L * (quarter(x)-1L) + 1L, 1L), years = ISOdate(year(x), 1L, 1L))) } +# Dates aren't simple numbers, and round.IDate doesn't accept numeric 'digits'. +is.numeric.IDate = function(x) FALSE chooseOpsMethod.IDate = function(x, y, mx, my, cl, reverse) inherits(y, "Date") @@ -255,6 +261,9 @@ round.ITime = function(x, digits = c("hours", "minutes"), ...) "class", "ITime")) } +# Day times aren't simple numbers, and round.ITime doesn't accept numeric 'digits'. +is.numeric.ITime = function(x) FALSE + trunc.ITime = function(x, units = c("hours", "minutes"), ...) { (setattr(switch(match.arg(units), @@ -279,7 +288,11 @@ unique.ITime = function(x, ...) { } # various methods to ensure ITime class is retained, #3628 -mean.ITime = seq.ITime = c.ITime = function(x, ...) as.ITime(NextMethod()) +mean.ITime = function(x, ...) { + x = unclass(x) + as.ITime(NextMethod()) +} +c.ITime = seq.ITime = function(...) as.ITime(NextMethod()) # create a data.table with IDate and ITime columns diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 00973ae3a5..4e3ea6d807 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -15090,6 +15090,7 @@ test(2054, DT[order(C)[1:5], B, verbose=TRUE], c('b', 'b', 'c', 'c', 'a'), test(2055.1, seq(from = as.ITime('00:00:00'), to = as.ITime('00:00:05'), by = 5L), as.ITime(c(0, 5L))) test(2055.2, c(as.ITime(0L), as.ITime(1L)), as.ITime(c(0L, 1L))) test(2055.3, mean(as.ITime(c(0L, 0L))), as.ITime(0L)) +test(2055.4, mean(as.IDate(c(0L, 0L))), as.IDate(0L)) # as.data.table.array some of dimnames are NULL, #3636 a = array(1:8, dim=c(2L,2L,2L), dimnames=list(NULL, NULL, as.character(1:2)))