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

Reply via email to