Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement start/end functions #242

Merged
merged 3 commits into from Jul 15, 2021
Merged

Implement start/end functions #242

merged 3 commits into from Jul 15, 2021

Conversation

DavisVaughan
Copy link
Member

Closes #232

This PR adds date_start() and date_end(), powered by calendar_start() and calendar_end().

library(clock)

x <- date_build(2019, 2:3, 2)
x
#> [1] "2019-02-02" "2019-03-02"

date_end(x, "month")
#> [1] "2019-02-28" "2019-03-31"

# in this case, the same as
set_day(x, "last")
#> [1] "2019-02-28" "2019-03-31"

x <- date_time_build(2019, 2:3, 2, 3, 30, 55, zone = "America/New_York")
x
#> [1] "2019-02-02 03:30:55 EST" "2019-03-02 03:30:55 EST"

# notice that this shifts the HMS components as well
date_end(x, "month")
#> [1] "2019-02-28 23:59:59 EST" "2019-03-31 23:59:59 EDT"

# unlike this
set_day(x, "last")
#> [1] "2019-02-28 03:30:55 EST" "2019-03-31 03:30:55 EDT"

Some notes on how we got here:

#232 suggested giving date_group() some way to return the end of the interval. This ends up being a little tricky to compute, and in some cases is tough to define - especially with pre-existing invalid dates. For example, calendar_group() currently handles invalid dates fairly intuitively, by choosing the left-hand side of the interval, valid dates always result in another valid date, and invalid dates result in either another invalid date or a valid date (if the left-hand side of the interval is a valid date).

library(clock)

x <- year_month_day(2019, 4, 30:31)

# [29, 30] [31, 32]
calendar_group(x, "day", n = 2)
#> <year_month_day<day>[2]>
#> [1] "2019-04-29" "2019-04-31"

# [29, 32]
calendar_group(x, "day", n = 4)
#> <year_month_day<day>[2]>
#> [1] "2019-04-29" "2019-04-29"

But what if the right hand side of the interval was chosen here? In the second example, I imagine that 2019-04-30 would stay 2019-04-30, as that is the last valid date in the month (i.e. we couldn't return 2019-04-32 even though that is the theoretical end of the interval). But what would the pre-existing invalid date of 2019-04-31 return? I feel like returning 2019-04-30 would be odd here, since that is less than the current invalid date (returning the left-hand side of the interval never has this problem). But we also can't return 2019-04-32, because that isn't even an invalid date. Returning 2019-04-31 as is feels just as weird, because it isn't the left or right hand side of any interval.

If we didn't have to consider these edge cases, then the implementation would be somewhat straightforward. It's just the lower_bound + (n - 1) then capped at the maximum valid component (i.e. the day at the end of the month in this case). Something like:

library(clock)

x <- year_month_day(2019, 4, 30:31)

# [29, 30] [31, 32]
day2 <- calendar_group(x, "day", n = 2)

new <- get_day(day2) + (2 - 1)
new <- pmin(new, get_day(set_day(day2, "last")))
set_day(day2, new)
#> <year_month_day<day>[2]>
#> [1] "2019-04-30" "2019-04-30"

# [29, 32]
day4 <- calendar_group(x, "day", n = 4)

new <- get_day(day4) + (4 - 1)
new <- pmin(new, get_day(set_day(day4, "last")))
set_day(day4, new)
#> <year_month_day<day>[2]>
#> [1] "2019-04-30" "2019-04-30"

But again, the invalid date results are a little odd.

Looking back at the issue, it seems @pnacht is really looking for some way to compute the start/end of the month (or year). I think that providing a way to do this directly is a better solution than tweaking date_group() to be possibly inconsistent.

@DavisVaughan DavisVaughan merged commit 9b09eec into master Jul 15, 2021
@DavisVaughan DavisVaughan deleted the feature/date-start-end branch July 15, 2021 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow date_group(bound = "upper") or similar
1 participant