r-lib / clock

A Date-Time Library for R
https://clock.r-lib.org
Other
97 stars 4 forks source link

Expanded getter options #360

Closed EmilHvitfeldt closed 8 months ago

EmilHvitfeldt commented 8 months ago

Problem

Right now all the getters only work under the smallest larger unit (not quite because of quarter). e.i. when you ask to get the day of datetime object, you get the day-in-month

x <- as.POSIXct("2019-03-01", tz = "America/New_York")

clock::get_day(x)
#> [1] 1

but you might want to know the day-in-year, which is a little bit of pain to get because of ✨ leap years ✨

Feature request

A way to get all combinations of x-in-y methods (super extra request, get result as decimal). What this would look like (if we exclude week and anything smaller than second.

this is a BIG ask, as the number of things are growing nice and fast. Hoping that there are some tricks that make this easy

trevorld commented 8 months ago

but you might want to know the day-in-year, which is a little bit of pain to get

Note {clock} does let you calculate some of these through calendar choice:

library("clock")
x <- as.POSIXct("2019-03-01", tz = "America/New_York")
x |> as_year_day() |> get_day() # day-in-year
x |> as_year_month_day() |> get_day() # day-in-month
x |> as_year_quarter_day() |> get_day() # day-in-quarter
x |> as_iso_year_week_day() |> get_day() # day-in-ISO-week
trevorld commented 8 months ago

You can calculate most of the rest by converting to an appropriate calendar, calculating the larger unit start with calendar_start(), and then converting back to POSIXct with as_date_time() and then use the as.double() method for difftime with the smaller unit as the units.

Here is an example "minute-in-quarter" calculation:

library("clock")
x <- as.POSIXct("2019-03-01", tz = "America/New_York")
x0 <- x |> 
    as_year_quarter_day() |> 
    calendar_start("quarter") |> 
    as_date_time(date_time_zone(x))
as.double(x - x0, units = "mins")
DavisVaughan commented 8 months ago

Yea as @trevorld says I think converting to an appropriate calendar type and using the relevant getter within the context of that calendar is the main way we avoid this explosive get-me-anything issue.

And his "minute-in-quarter" example is good too. You can also do that kind of thing completely within clock too (it requires you to know a little of the theory but not much)

library(clock)

x <- as_year_quarter_day(year_month_day_parse("2019-03-01T05:32", precision = "minute"))

start <- x |> 
  calendar_start("quarter")

x
#> <year_quarter_day<January><minute>[1]>
#> [1] "2019-Q1-60T05:32"
start
#> <year_quarter_day<January><minute>[1]>
#> [1] "2019-Q1-01T00:00"

as_naive_time(x) - as_naive_time(start)
#> <duration<minute>[1]>
#> [1] 85292
DavisVaughan commented 8 months ago

day-of-year is one of the vignette examples too, since i figured it would be common to do that https://clock.r-lib.org/articles/recipes.html#day-of-the-year