From 9b76049f59fecb0b068735e70f9c9c4b0aad59d6 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Fri, 28 Feb 2025 10:23:03 +0300 Subject: [PATCH 1/3] Register the full IDate S3 class for S4 dispatch As recommended by ?setOldClass, register c("IDate", "Date"), not just "IDate". --- R/AllS4.R | 2 +- inst/tests/S4.Rraw | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/R/AllS4.R b/R/AllS4.R index 89c2d3f815..d77330561a 100644 --- a/R/AllS4.R +++ b/R/AllS4.R @@ -16,7 +16,7 @@ methods::setAs("data.table", "data.frame", function(from) { as.data.frame(from) }) -methods::setOldClass("IDate") +methods::setOldClass(c("IDate", "Date")) methods::setOldClass("ITime") methods::setAs("character", "IDate", function(from) as.IDate(from)) diff --git a/inst/tests/S4.Rraw b/inst/tests/S4.Rraw index 19a595c08b..aaff68f76c 100644 --- a/inst/tests/S4.Rraw +++ b/inst/tests/S4.Rraw @@ -118,3 +118,11 @@ test(7.1, is.data.table(DF@x)) # Similar code for under-allocated data.tables in S4 slots, #6704 setClass("DataTable", slots=c(x="data.table")) test(7.2, options=c(datatable.alloccol=0L), {DT = new("DataTable", x=data.table(a=1)); DT@x[, b := 2L]; DT@x$b}, 2L) # NB: requires assigning DT to test assignment back to that object + +# IDate was not visible as Date to S4 dispatch, #6839 +CustomDurationClass <- setClass("CustomDurationClass", contains = "integer") +setGeneric("%foo%", function(e1, e2) stop("dispatch to default method")) +setMethod(`%foo%`, c("Date", "CustomDurationClass"), function (e1, e2) e1 - e2@.Data) +test(8, as.IDate("2025-03-01") %foo% CustomDurationClass(1), as.IDate("2025-02-28")) +removeGeneric("%foo%") +removeClass("CustomDurationClass") From 649d117daff7d4c998e915587acb458b463cb547 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Fri, 28 Feb 2025 12:53:59 +0300 Subject: [PATCH 2/3] NEWS entry --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index f22d066253..42bf0164f0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,10 @@ 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 match `DT[order(...)]` behavior with respect to locale. Thanks @rikivillalba for the suggestion and PR. +## BUG FIXES + +1. Custom binary operators from the `lubridate` package now work with objects of class `IDate` as with a `Date` subclass, [#6839](https://github.com/Rdatatable/data.table/issues/6839). Thanks @emallickhossain for the report and @aitap for the fix. + # data.table [v1.17.0](https://github.com/Rdatatable/data.table/milestone/34) (20 Feb 2025) ## POTENTIALLY BREAKING CHANGES From f98421875bd9f5bc9a3ddf47703b56c0f042531e Mon Sep 17 00:00:00 2001 From: Ivan K Date: Fri, 28 Feb 2025 13:00:09 +0300 Subject: [PATCH 3/3] Remove setOldClass("data.frame") Instead of defining and exporting an S4 class for data.frame (which we don't own), keep setOldClass(c("data.table", "data.frame")) (which we do). --- R/AllS4.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/AllS4.R b/R/AllS4.R index d77330561a..2b3a8e0905 100644 --- a/R/AllS4.R +++ b/R/AllS4.R @@ -3,7 +3,6 @@ if ("package:data.table" %in% search()) stopf("data.table package loaded. When d ## Allows data.table to be defined as an object of an S4 class, ## or even have data.table be a super class of an S4 class. -methods::setOldClass(c('data.frame')) methods::setOldClass(c('data.table', 'data.frame')) ## as(some.data.frame, "data.table")