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
Duncan Murdoch
2024-Feb-08 18:03 UTC
[Rd] round.Date and trunc.Date not working / implemented
This is a workaround, and could be the basis for a round.Date improvement: date <- Sys.Date() as.Date(round(as.POSIXct(date), "years")) as.Date(round(as.POSIXct(Sys.Date() + 180), "years")) Duncan Murdoch On 08/02/2024 12:23 p.m., Henrik Bengtsson wrote:> 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.Date > function (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-devel > > On 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 > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
Apparently Analagous Threads
- round.Date and trunc.Date not working / implemented
- round.Date and trunc.Date not working / implemented
- round.Date and trunc.Date not working / implemented
- round.Date and trunc.Date not working / implemented
- round.Date and trunc.Date not working / implemented