reconhub / aweek

Convert dates to arbitrary week definitions :calendar:
https://www.repidemicsconsortium.org/aweek
Other
17 stars 4 forks source link

Allow for arithmetic manipulation of `aweek` objects #27

Open jpolonsky opened 5 years ago

jpolonsky commented 5 years ago

It would be great if one could work with aweek objects, e.g. by adding and subtracting to get the precedent or subsequent weeks, akin to what is possible with dates. Something like

aweek::date2week(Sys.Date()) + 1

zkamvar commented 5 years ago

I've thought about this before and didn't really know how best to handle it since the granularity of aweek objects goes down to the day level.

At the moment, what you propose is currently possible via the following (albiet awkward) syntax:

library("aweek")
set_week_start("Monday")
d <- Sys.Date() + (-3:3)
w <- as.aweek(d)
w
#> <aweek start: Monday>
#> [1] "2019-W29-3" "2019-W29-4" "2019-W29-5" "2019-W29-6" "2019-W29-7"
#> [6] "2019-W30-1" "2019-W30-2"
w2 <- as.aweek(as.Date(w) + (1 * 7))
w2
#> <aweek start: Monday>
#> [1] "2019-W30-3" "2019-W30-4" "2019-W30-5" "2019-W30-6" "2019-W30-7"
#> [6] "2019-W31-1" "2019-W31-2"

Created on 2019-07-20 by the reprex package (v0.3.0)

It's very possible to define - and + methods for aweek objects, but the question becomes:

What should the granularity be? If I do w + 1, will it add a week or a day?

jpolonsky commented 5 years ago

Would it be possible to have 2 separate granularities, depending on the object? It seems you have 2 possible objects, both of which it would be highly useful to manipulate - one which gives the day, and one which more usefully (IMO) gives the week:

aweek::date2week(Sys.Date())
#> <aweek start: Monday>
#> [1] "2019-W29-7"
aweek::date2week(Sys.Date(), floor_day = TRUE)
#> <aweek start: Monday>
#> [1] "2019-W29"

Created on 2019-07-21 by the reprex package (v0.3.0)

Would it therefore be possible to do, for example:

aweek::date2week(Sys.Date()) + 1
#> Error in aweek::date2week(Sys.Date()) + 1: non-numeric argument to binary operator
aweek::date2week(Sys.Date(), floor_day = TRUE) + 1
#> Error in aweek::date2week(Sys.Date(), floor_day = TRUE) + 1: non-numeric argument to binary operator

Created on 2019-07-21 by the reprex package (v0.3.0)

and, in the first instance, add a day, while, in the second, add a week?

zkamvar commented 5 years ago

Would it be possible to have 2 separate granularities, depending on the object? It seems you have 2 possible objects, both of which it would be highly useful to manipulate - one which gives the day, and one which more usefully (IMO) gives the week:

I don't think it's wise to have two separate granularities here because the YYYY-Www construct is merely shorthand for YYYY-Www-1, so both types are valid in the same vector:

aweek::as.aweek(c("2019-W10-2", "2019-W20"))
#> <aweek start: Monday>
#> [1] "2019-W10-2" "2019-W20"

Created on 2019-07-22 by the reprex package (v0.3.0)

I think, given that the granularity for the object is a single day, I'll have the + and - operator act the same as the Date class and then make wrapper functions like aweek::add_week() and aweek::minus_week() that will multiply the input by 7.

jpolonsky commented 5 years ago

Sounds like a great plan!

ship_it