diff --git a/NEWS.md b/NEWS.md index fc6944943..6a107bcf9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,6 +8,8 @@ 1. `data.table(x=1, )`, where `` is an expression resulting in a 1-column matrix without column names, will eventually have names `x` and `V2`, not `x` and `V1`, consistent with `data.table(x=1, )` where `` results in an atomic vector, for example `data.table(x=1, cbind(1))` and `data.table(x=1, 1)` will both have columns named `x` and `V2`. In this release, the matrix case continues to be named `V1`, but the new behavior can be activated by setting `options(datatable.old.matrix.autoname)` to `FALSE`. See point 5 under Bug Fixes for more context; this change will provide more internal consistency as well as more consistency with `data.frame()`. +2. `t1 - t2`, where both `t1` and `t2` are `IDate`, will eventually have class `difftime`, consistent with the case where `t1` and `t2` are both `Date`. You can activate the new behavior by setting `options(datatable.old.diff.time = FALSE)`. See point 17 under Bug Fixes for more context. + ### NEW FEATURES 1. New `sort_by()` method for data.tables, [#6662](https://github.com/Rdatatable/data.table/issues/6662). It uses `forder()` to improve upon the data.frame method and also matches `DT[order(...)]` behavior with respect to locale. Thanks @rikivillalba for the suggestion and PR. diff --git a/R/IDateTime.R b/R/IDateTime.R index 2a06ef2c7..db81cc654 100644 --- a/R/IDateTime.R +++ b/R/IDateTime.R @@ -130,8 +130,10 @@ chooseOpsMethod.IDate = function(x, y, mx, my, cl, reverse) inherits(y, "Date") } ans = as.integer(unclass(e1) - unclass(e2)) if (inherits(e2, "Date")) { - setattr(ans, "class", "difftime") - setattr(ans, "units", "days") + if (!isTRUE(getOption("datatable.old.diff.idate"))) { + setattr(ans, "class", "difftime") + setattr(ans, "units", "days") + } } else { setattr(ans, "class", c("IDate", "Date")) } diff --git a/R/onLoad.R b/R/onLoad.R index 2e0bd870b..986f74250 100644 --- a/R/onLoad.R +++ b/R/onLoad.R @@ -92,7 +92,8 @@ datatable.auto.index=TRUE, # DT[col=="val"] to auto add index so 2nd time faster datatable.use.index=TRUE, # global switch to address #1422 datatable.prettyprint.char=NULL, # FR #1091 - datatable.old.matrix.autoname=TRUE # #7145: how data.table(x=1, matrix(1)) is auto-named set to change + datatable.old.matrix.autoname=TRUE, # #7145: how data.table(x=1, matrix(1)) is auto-named set to change + datatable.old.diff.idate=TRUE # whether - gets difftime class set to change ) opts = opts[!names(opts) %chin% names(options())] options(opts) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index d7ffc476b..99686b25c 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -10342,7 +10342,7 @@ test(1673.1, TT + 4L, as.IDate("2016-04-29")) test(1673.2, TT + 4, as.IDate("2016-04-29")) test(1673.3, TT - 3, as.IDate("2016-04-22")) test(1673.4, TT - 3L, as.IDate("2016-04-22")) -test(1673.5, all.equal(as.IDate("2016-04-28") - as.IDate("2016-04-20"), as.difftime(8, units='days'))) +test(1673.5, options=c(datatable.old.diff.idate=FALSE), all.equal(as.IDate("2016-04-28") - as.IDate("2016-04-20"), as.difftime(8, units='days'))) # test for radix integer order when MAXINT is present AND decreasing=TRUE AND na.last=FALSE @@ -21587,12 +21587,16 @@ test(2335.6, isoyear(as.Date("2019-12-30")), 2020L) # t1-t2 for Date/IDate should be consistent, modulo storage mode #4979 t1 = as.IDate("2025-07-01") t2 = as.IDate("2025-06-01") -test(2336.1, all.equal(as.Date(t1) - as.Date(t2), t1 - t2)) -test(2336.2, all.equal(as.Date(t2) - as.Date(t1), t2 - t1)) -test(2336.3, all.equal(as.Date(t1) - t2, t1 - t2)) -test(2336.4, all.equal(as.Date(t2) - t1, t2 - t1)) -test(2336.5, all.equal(t1 - as.Date(t2), t1 - t2)) -test(2336.6, all.equal(t2 - as.Date(t1), t2 - t1)) +test(2336.01, options=c(datatable.old.diff.idate=FALSE), all.equal(as.Date(t1) - as.Date(t2), t1 - t2)) +test(2336.02, options=c(datatable.old.diff.idate=FALSE), all.equal(as.Date(t2) - as.Date(t1), t2 - t1)) +test(2336.03, options=c(datatable.old.diff.idate=FALSE), all.equal(as.Date(t1) - t2, t1 - t2)) +test(2336.04, options=c(datatable.old.diff.idate=FALSE), all.equal(as.Date(t2) - t1, t2 - t1)) +test(2336.05, all.equal(t1 - as.Date(t2), t1 - t2)) +test(2336.06, all.equal(t2 - as.Date(t1), t2 - t1)) +test(2336.07, all.equal(as.numeric(as.Date(t1) - as.Date(t2)), as.numeric(t1 - t2))) +test(2336.08, all.equal(as.numeric(as.Date(t2) - as.Date(t1)), as.numeric(t2 - t1))) +test(2336.09, all.equal(as.numeric(as.Date(t1) - t2), as.numeric(t1 - t2))) +test(2336.10, all.equal(as.numeric(as.Date(t2) - t1), as.numeric(t2 - t1))) # fwrite: allow dec=',' with single column, #7227 test(2337.1, fwrite(data.table(1), dec=","), NULL) diff --git a/man/data.table-options.Rd b/man/data.table-options.Rd index 63c79fdf6..82459ec00 100644 --- a/man/data.table-options.Rd +++ b/man/data.table-options.Rd @@ -114,6 +114,10 @@ expressions like \code{data.table(x=1, cbind(1))} will be named. When \code{TRUE}, it will be named \code{V1}, otherwise it will be named \code{V2}. } + \item{\code{datatable.old.diff.idate}}{Logical, default \code{TRUE}. Governs whether \code{t1 - t2}, + where \code{t1} and \code{t2} are both class \code{IDate}, gains the S3 class \code{difftime}. + When \code{TRUE}, this class is assigned (with \code{units="days"}). + } } }