Rui Barradas
2024-Feb-08 17:05 UTC
[Rd] round.Date and trunc.Date not working / implemented
?s 14:36 de 08/02/2024, Olivier Benz via R-devel escreveu:>> On 8 Feb 2024, at 15:15, Martin Maechler <maechler at stat.math.ethz.ch> wrote: >> >>>>>>> Ji?? Moravec >>>>>>> on Wed, 7 Feb 2024 10:23:15 +1300 writes: >> >>> This is my first time working with dates, so if the answer is "Duh, work >>> with POSIXt", please ignore it. >> >>> Why is not `round.Date` and `trunc.Date` "implemented" for `Date`? >> >>> Is this because `Date` is (mostly) a virtual class setup for a better >>> inheritance or is that something that is just missing? (like >>> `sort.data.frame`). Would R core welcome a patch? >> >>> I decided to convert some dates to date using `as.Date` function, which >>> converts to a plain `Date` class, because that felt natural. >> >>> But then when trying to round to closest year, I have realized that the >>> `round` and `trunc` for `Date` do not behave as for `POSIXt`. >> >>> I would assume that these will have equivalent output: >> >>> Sys.time() |> round("years") # 2024-01-01 NZDT >> >>> Sys.Date() |> round("years") # Error in round.default(...): non-numeric >>> argument to mathematical function >> >> >>> Looking at the code (and reading the documentation more carefully) shows >>> the issue, but this looks like an omission that should be patched. >> >>> -- Jirka >> >> You are wrong: They *are* implemented, >> both even visible since they are in the 'base' package! >> >> ==> they have help pages you can read .... >> >> Here are examples: >> >>> trunc(Sys.Date()) >> [1] "2024-02-08" >>> trunc(Sys.Date(), "month") >> [1] "2024-02-01" >>> trunc(Sys.Date(), "year") >> [1] "2024-01-01" >>> >> > > Maybe he meant > > r$> Sys.time() |> round.POSIXt("years") > [1] "2024-01-01 CET" > > r$> Sys.Date() |> round.POSIXt("years") > [1] "2024-01-01 UTC" > > The only difference is the timezone > >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-develHello, You are right that the timezones are different but Sys.date() returns an object of class "Date" so the method called is not that one. Here an example with trunc. Sys.Date() |> class() Sys.Date() |> trunc("years") Sys.Date() |> trunc.Date("years") Sys.Date() |> trunc.POSIXt("years") As for the OP, the problem is thhat the generic roun())) doesn't have unit argument. So I am nnnot understanding why round.POSIXt works. Sys.Date() |> round("years") #> Error in round.default(structure(19761, class = "Date"), "years"): non-numeric argument to mathematical function Sys.Date() |> round.Date("years") #> Error in NextMethod(): generic function not specified Sys.Date() |> round.POSIXt("years") #> [1] "2024-01-01 UTC" Sys.Date() |> round.POSIXt("months") #> [1] "2024-02-01 UTC" Sys.Date() |> round.POSIXt("days") #> [1] "2024-02-08 UTC" Hope this helps, Rui Barradas -- Este e-mail foi analisado pelo software antiv?rus AVG para verificar a presen?a de v?rus. www.avg.com
Henrik Bengtsson
2024-Feb-08 17:23 UTC
[Rd] round.Date and trunc.Date not working / implemented
Technically, there is a round() for 'Date' objects, but it doesn't seem very useful, because it basically just fall back to the default round() method, which only takes the 'digits' argument. Here's an example:> date <- Sys.Date() > class(date)[1] "Date" We see that there are only two round() methods in addition to the implicit built-in one;> methods("round")[1] round.Date round.POSIXt see '?methods' for accessing help and source code Looking at round() for 'Date';> round.Datefunction (x, ...) { .Date(NextMethod(), oldClass(x)) } <environment: namespace:base> we see that it defers to the next method here, which is the built-in one. The built-in one, only accepts 'digits', which does nothing for digits >= 0. For digits < 0, it rounds to power of ten, e.g.> date[1] "2024-02-08"> round(date, digits = 0)[1] "2024-02-08"> round(date, digits = 1)[1] "2024-02-08"> round(date, digits = 2)[1] "2024-02-08"> round(date, digits = -1)[1] "2024-02-07"> round(date, digits = -2)[1] "2024-03-18"> round(date, digits = -3)[1] "2024-10-04"> round(date, digits = -4)[1] "2024-10-04"> round(date, digits = -5)[1] "1970-01-01" So, although technically invalid, OPs remark is a valid one. I'd also expect `round()` for Date to support 'units' similar to timestamps, e.g.> time <- Sys.time() > class(time)[1] "POSIXct" "POSIXt"> time[1] "2024-02-08 09:17:02 PST"> round(time, units = "days")[1] "2024-02-08 PST"> round(time, units = "months")[1] "2024-02-01 PST"> round(time, units = "years")[1] "2024-01-01 PST" So, I agree with OP that one would expect:> round(date, units = "days")[1] "2024-02-08"> round(date, units = "months")[1] "2024-02-01"> round(date, units = "years")[1] "2024-01-01" to also work here. FWIW, I don't think we want to encourage circumventing the S3 generic and calling S3 methods directly, i.e. I don't recommend doing things like round.POSIXt(...). Ideally, all S3 methods in R would be non-exported, but some remain exported for legacy reason. But, I think we should treat them as if they in the future will become non-exported. /Henrik On Thu, Feb 8, 2024 at 8:18?AM Olivier Benz via R-devel <r-devel at r-project.org> wrote:> > > On 8 Feb 2024, at 15:15, Martin Maechler <maechler at stat.math.ethz.ch> wrote: > > > >>>>>> Ji?? Moravec > >>>>>> on Wed, 7 Feb 2024 10:23:15 +1300 writes: > > > >> This is my first time working with dates, so if the answer is "Duh, work > >> with POSIXt", please ignore it. > > > >> Why is not `round.Date` and `trunc.Date` "implemented" for `Date`? > > > >> Is this because `Date` is (mostly) a virtual class setup for a better > >> inheritance or is that something that is just missing? (like > >> `sort.data.frame`). Would R core welcome a patch? > > > >> I decided to convert some dates to date using `as.Date` function, which > >> converts to a plain `Date` class, because that felt natural. > > > >> But then when trying to round to closest year, I have realized that the > >> `round` and `trunc` for `Date` do not behave as for `POSIXt`. > > > >> I would assume that these will have equivalent output: > > > >> Sys.time() |> round("years") # 2024-01-01 NZDT > > > >> Sys.Date() |> round("years") # Error in round.default(...): non-numeric > >> argument to mathematical function > > > > > >> Looking at the code (and reading the documentation more carefully) shows > >> the issue, but this looks like an omission that should be patched. > > > >> -- Jirka > > > > You are wrong: They *are* implemented, > > both even visible since they are in the 'base' package! > > > > ==> they have help pages you can read .... > > > > Here are examples: > > > >> trunc(Sys.Date()) > > [1] "2024-02-08" > >> trunc(Sys.Date(), "month") > > [1] "2024-02-01" > >> trunc(Sys.Date(), "year") > > [1] "2024-01-01" > >> > > > > Maybe he meant > > r$> Sys.time() |> round.POSIXt("years") > [1] "2024-01-01 CET" > > r$> Sys.Date() |> round.POSIXt("years") > [1] "2024-01-01 UTC" > > The only difference is the timezone > > > ______________________________________________ > > R-devel at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-develOn Thu, Feb 8, 2024 at 9:06?AM Rui Barradas <ruipbarradas at sapo.pt> wrote:> > ?s 14:36 de 08/02/2024, Olivier Benz via R-devel escreveu: > >> On 8 Feb 2024, at 15:15, Martin Maechler <maechler at stat.math.ethz.ch> wrote: > >> > >>>>>>> Ji?? Moravec > >>>>>>> on Wed, 7 Feb 2024 10:23:15 +1300 writes: > >> > >>> This is my first time working with dates, so if the answer is "Duh, work > >>> with POSIXt", please ignore it. > >> > >>> Why is not `round.Date` and `trunc.Date` "implemented" for `Date`? > >> > >>> Is this because `Date` is (mostly) a virtual class setup for a better > >>> inheritance or is that something that is just missing? (like > >>> `sort.data.frame`). Would R core welcome a patch? > >> > >>> I decided to convert some dates to date using `as.Date` function, which > >>> converts to a plain `Date` class, because that felt natural. > >> > >>> But then when trying to round to closest year, I have realized that the > >>> `round` and `trunc` for `Date` do not behave as for `POSIXt`. > >> > >>> I would assume that these will have equivalent output: > >> > >>> Sys.time() |> round("years") # 2024-01-01 NZDT > >> > >>> Sys.Date() |> round("years") # Error in round.default(...): non-numeric > >>> argument to mathematical function > >> > >> > >>> Looking at the code (and reading the documentation more carefully) shows > >>> the issue, but this looks like an omission that should be patched. > >> > >>> -- Jirka > >> > >> You are wrong: They *are* implemented, > >> both even visible since they are in the 'base' package! > >> > >> ==> they have help pages you can read .... > >> > >> Here are examples: > >> > >>> trunc(Sys.Date()) > >> [1] "2024-02-08" > >>> trunc(Sys.Date(), "month") > >> [1] "2024-02-01" > >>> trunc(Sys.Date(), "year") > >> [1] "2024-01-01" > >>> > >> > > > > Maybe he meant > > > > r$> Sys.time() |> round.POSIXt("years") > > [1] "2024-01-01 CET" > > > > r$> Sys.Date() |> round.POSIXt("years") > > [1] "2024-01-01 UTC" > > > > The only difference is the timezone > > > >> ______________________________________________ > >> R-devel at r-project.org mailing list > >> https://stat.ethz.ch/mailman/listinfo/r-devel > > ______________________________________________ > > R-devel at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > Hello, > > You are right that the timezones are different but Sys.date() returns an > object of class "Date" so the method called is not that one. > Here an example with trunc. > > > Sys.Date() |> class() > Sys.Date() |> trunc("years") > Sys.Date() |> trunc.Date("years") > Sys.Date() |> trunc.POSIXt("years") > > > As for the OP, the problem is thhat the generic roun())) doesn't have > unit argument. So I am nnnot understanding why round.POSIXt works. > > > Sys.Date() |> round("years") > #> Error in round.default(structure(19761, class = "Date"), "years"): > non-numeric argument to mathematical function > Sys.Date() |> round.Date("years") > #> Error in NextMethod(): generic function not specified > > Sys.Date() |> round.POSIXt("years") > #> [1] "2024-01-01 UTC" > Sys.Date() |> round.POSIXt("months") > #> [1] "2024-02-01 UTC" > Sys.Date() |> round.POSIXt("days") > #> [1] "2024-02-08 UTC" > > > Hope this helps, > > Rui Barradas > > > > -- > Este e-mail foi analisado pelo software antiv?rus AVG para verificar a presen?a de v?rus. > www.avg.com > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel