Skip to content

Commit cfa9f49

Browse files
Use chooseOpsMethod to get Date-IDate correct (#7213)
* Use chooseOpsMethod to get Date-IDate correct * do change for difftime result * correct issue # * correct IDate-days * not available on old R Co-authored-by: aitap <[email protected]> --------- Co-authored-by: aitap <[email protected]>
1 parent 84b0e32 commit cfa9f49

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ if (getRversion() >= "3.6.0") {
155155
export(as.IDate,as.ITime,IDateTime)
156156
export(second,minute,hour,yday,wday,mday,week,isoweek,isoyear,month,quarter,year,yearmon,yearqtr)
157157

158+
if (getRversion() >= "4.3.0") S3method(chooseOpsMethod, IDate)
158159
S3method("[", ITime)
159160
S3method("+", IDate)
160161
S3method("-", IDate)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
104104
16. `between()` is now more robust with `integer64` arguments. Combining small integer `x` with certain large `integer64` bounds no longer misinterprets the bounds as `double`; if a `double` bound cannot be losslessly converted into `integer64` for comparison with `integer64` `x`, an error is signalled instead of returning a wrong answer with a warning; [#7164](https://github.com/Rdatatable/data.table/issues/7164). Thanks @aitap for the bug report and the fix.
105105
106+
17. `t1 - t2`, where one is an `IDate` and the other is a `Date`, are now consistent with the case where both are `IDate` or both are `Date`, [#4749](https://github.com/Rdatatable/data.table/issues/4749). Thanks @George9000 for the report and @MichaelChirico for the fix.
107+
106108
### NOTES
107109
108110
1. The following in-progress deprecations have proceeded:

R/IDateTime.R

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ round.IDate = function(x, digits=c("weeks", "months", "quarters", "years"), ...)
9191
years = ISOdate(year(x), 1L, 1L)))
9292
}
9393

94+
chooseOpsMethod.IDate = function(x, y, mx, my, cl, reverse) inherits(y, "Date")
95+
9496
#Adapted from `+.Date`
9597
`+.IDate` = function(e1, e2) {
9698
if (nargs() == 1L)
@@ -115,7 +117,7 @@ round.IDate = function(x, digits=c("weeks", "months", "quarters", "years"), ...)
115117
if (storage.mode(e1) != "integer")
116118
internal_error("storage mode of IDate is somehow no longer integer") # nocov
117119
if (nargs() == 1L)
118-
stopf("unary - is not defined for \"IDate\" objects")
120+
stopf('unary - is not defined for "IDate" objects')
119121
if (inherits(e2, "difftime"))
120122
internal_error("difftime objects may not be subtracted from IDate, but Ops dispatch should have intervened to prevent this") # nocov
121123

@@ -127,7 +129,12 @@ round.IDate = function(x, digits=c("weeks", "months", "quarters", "years"), ...)
127129
# ii) .Date was newly exposed in R some time after 3.4.4
128130
}
129131
ans = as.integer(unclass(e1) - unclass(e2))
130-
if (!inherits(e2, "Date")) setattr(ans, "class", c("IDate", "Date"))
132+
if (inherits(e2, "Date")) {
133+
setattr(ans, "class", "difftime")
134+
setattr(ans, "units", "days")
135+
} else {
136+
setattr(ans, "class", c("IDate", "Date"))
137+
}
131138
ans
132139
}
133140

inst/tests/tests.Rraw

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10342,7 +10342,7 @@ test(1673.1, TT + 4L, as.IDate("2016-04-29"))
1034210342
test(1673.2, TT + 4, as.IDate("2016-04-29"))
1034310343
test(1673.3, TT - 3, as.IDate("2016-04-22"))
1034410344
test(1673.4, TT - 3L, as.IDate("2016-04-22"))
10345-
test(1673.5, as.IDate("2016-04-28") - as.IDate("2016-04-20"), 8L)
10345+
test(1673.5, all.equal(as.IDate("2016-04-28") - as.IDate("2016-04-20"), as.difftime(8, units='days')))
1034610346

1034710347

1034810348
# test for radix integer order when MAXINT is present AND decreasing=TRUE AND na.last=FALSE
@@ -21574,3 +21574,13 @@ test(2335.3, isoyear(as.IDate("2023-08-15")), 2023L) # Normal mid-year case
2157421574
test(2335.4, isoyear(as.IDate(c("2019-12-30", "2016-01-01", "2023-08-15"))),c(2020L, 2015L, 2023L))
2157521575
test(2335.5, isoyear("2019-12-30"), 2020L)
2157621576
test(2335.6, isoyear(as.Date("2019-12-30")), 2020L)
21577+
21578+
# t1-t2 for Date/IDate should be consistent, modulo storage mode #4979
21579+
t1 = as.IDate("2025-07-01")
21580+
t2 = as.IDate("2025-06-01")
21581+
test(2336.1, all.equal(as.Date(t1) - as.Date(t2), t1 - t2))
21582+
test(2336.2, all.equal(as.Date(t2) - as.Date(t1), t2 - t1))
21583+
test(2336.3, all.equal(as.Date(t1) - t2, t1 - t2))
21584+
test(2336.4, all.equal(as.Date(t2) - t1, t2 - t1))
21585+
test(2336.5, all.equal(t1 - as.Date(t2), t1 - t2))
21586+
test(2336.6, all.equal(t2 - as.Date(t1), t2 - t1))

0 commit comments

Comments
 (0)