Martin, Yes, I missed that those have `Summary.*` methods, thanks!
Tweaking those to respect `finite = TRUE` sounds great. It seems like it might be a little tricky since the Summary methods call `NextMethod()`, and `range.default()` uses `is.numeric()` to determine whether or not to apply `finite`. Because `is.numeric.Date()` is defined, that always returns `FALSE` for Dates (and POSIXt). Because of that, it may still be easier to just write a specific `range.Date()` method, but I'm not sure. -Davis On Sat, Apr 29, 2023 at 4:47 PM Martin Maechler <maech...@stat.math.ethz.ch> wrote: > > >>>>> Davis Vaughan via R-devel > >>>>> on Fri, 28 Apr 2023 11:12:27 -0400 writes: > > > Hi all, > > > I noticed that `range.default()` has a nice `finite = > > TRUE` argument, but it doesn't actually apply to Date or > > POSIXct due to how `is.numeric()` works. > > Well, I think it would / should never apply: > > range() belongs to the "Summary" group generics (as min, max, ...) > > and there *are* Summary.Date() and Summary.POSIX{c,l}t() methods. > > Without checking further for now, I think you are indirectly > suggesting to enhance these three Summary.*() methods so they do > obey 'finite = TRUE' . > > I think I agree they should. > > Martin > > > ``` x <- .Date(c(0, Inf, 1, 2, Inf)) x #> [1] "1970-01-01" > > "Inf" "1970-01-02" "1970-01-03" "Inf" > > > # Darn! range(x, finite = TRUE) #> [1] "1970-01-01" "Inf" > > > # What I want .Date(range(unclass(x), finite = TRUE)) #> > > [1] "1970-01-01" "1970-01-03" ``` > > > I think `finite = TRUE` would be pretty nice for Dates in > > particular. > > > As a motivating example, sometimes you have ranges of > > dates represented by start/end pairs. It is fairly natural > > to represent an event that hasn't ended yet with an > > infinite date. If you need to then compute a sequence of > > dates spanning the full range of the start/end pairs, it > > would be nice to be able to use `range(finite = TRUE)` to > > do so: > > > ``` start <- as.Date(c("2019-01-05", "2019-01-10", > > "2019-01-11", "2019-01-14")) end <- > > as.Date(c("2019-01-07", NA, "2019-01-14", NA)) > > end[is.na(end)] <- Inf > > > # `end = Inf` means that the event hasn't "ended" yet > > data.frame(start, end) #> start end #> 1 2019-01-05 > > 2019-01-07 #> 2 2019-01-10 Inf #> 3 2019-01-11 2019-01-14 > > #> 4 2019-01-14 Inf > > > # Create a full sequence along all days in start/end range > > <- .Date(range(unclass(c(start, end)), finite = TRUE)) > > seq(range[1], range[2], by = 1) #> [1] "2019-01-05" > > "2019-01-06" "2019-01-07" "2019-01-08" "2019-01-09" #> [6] > > "2019-01-10" "2019-01-11" "2019-01-12" "2019-01-13" > > "2019-01-14" ``` > > > It seems like one option is to create a `range.Date()` > > method that unclasses, forwards the arguments on to a > > second call to `range()`, and then reclasses? > > > ``` range.Date <- function(x, ..., na.rm = FALSE, finite = > > FALSE) { .Date(range(unclass(x), na.rm = na.rm, finite = > > finite), oldClass(x)) } ``` > > > This is similar to how `rep.Date()` works. > > > Thanks, Davis Vaughan > > > ______________________________________________ > > R-devel@r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel