@@ -769,28 +769,54 @@ gcd_num <- function(dividends, ..., rrtol = 1e-6, pqlim = 1e6, irtol = 1e-6) {
769
769
vctrs :: vec_cast(numeric_gcd , dividends )
770
770
}
771
771
772
- # ' Use max valid period as guess for `period` of `ref_time_values`
773
- # '
774
- # ' @param ref_time_values Vector containing time-interval-like or time-like
775
- # ' data, with at least two distinct values, [`diff`]-able (e.g., a
776
- # ' `time_value` or `version` column), and should have a sensible result from
777
- # ' adding `is.numeric` versions of its `diff` result (via `as.integer` if its
778
- # ' `typeof` is `"integer"`, otherwise via `as.numeric`).
779
- # ' @param ref_time_values_arg Optional, string; name to give `ref_time_values`
780
- # ' in error messages. Defaults to quoting the expression the caller fed into
781
- # ' the `ref_time_values` argument.
782
- # ' @return `is.numeric`, length 1; attempts to match `typeof(ref_time_values)`
783
- guess_period <- function (ref_time_values , ref_time_values_arg = rlang :: caller_arg(ref_time_values )) {
784
- sorted_distinct_ref_time_values <- sort(unique(ref_time_values ))
785
- if (length(sorted_distinct_ref_time_values ) < 2L ) {
786
- cli_abort(" Not enough distinct values in {.code {ref_time_values_arg}} to guess the period." , ref_time_values_arg )
772
+ # ' Use max valid period as guess for `period` of `time_values`
773
+ # '
774
+ # ' `r lifecycle::badge("experimental")`
775
+ # '
776
+ # ' @param time_values Vector containing time-interval-like or time-point-like
777
+ # ' data, with at least two distinct values.
778
+ # ' @param time_values_arg Optional, string; name to give `time_values` in error
779
+ # ' messages. Defaults to quoting the expression the caller fed into the
780
+ # ' `time_values` argument.
781
+ # ' @param ... Should be empty, there to satisfy the S3 generic.
782
+ # ' @return length-1 vector; `r lifecycle::badge("experimental")` class will
783
+ # ' either be the same class as [`base::diff()`] on such time values, an
784
+ # ' integer, or a double, such that all `time_values` can be exactly obtained
785
+ # ' by adding `k * result` for an integer k, and such that there is no smaller
786
+ # ' `result` that can achieve this.
787
+ # '
788
+ # ' @export
789
+ guess_period <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
790
+ UseMethod(" guess_period" )
791
+ }
792
+
793
+ # ' @export
794
+ guess_period.default <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
795
+ rlang :: check_dots_empty()
796
+ sorted_distinct_time_values <- sort(unique(time_values ))
797
+ if (length(sorted_distinct_time_values ) < 2L ) {
798
+ cli_abort(" Not enough distinct values in {.code {time_values_arg}} to guess the period." ,
799
+ class = " epiprocess__guess_period__not_enough_times" ,
800
+ time_values = time_values
801
+ )
787
802
}
788
- skips <- diff(sorted_distinct_ref_time_values )
789
- decayed_skips <-
790
- if (typeof(skips ) == " integer" ) {
791
- as.integer(skips )
792
- } else {
793
- as.numeric(skips )
794
- }
795
- gcd_num(decayed_skips )
803
+ skips <- diff(sorted_distinct_time_values )
804
+ # Certain diff results have special classes or attributes; use vctrs to try to
805
+ # appropriately destructure for gcd_num, then restore to their original class
806
+ # & attributes.
807
+ skips_data <- vctrs :: vec_data(skips )
808
+ period_data <- gcd_num(skips_data , rrtol = 0 )
809
+ vctrs :: vec_restore(period_data , skips )
810
+ }
811
+
812
+ # `full_seq()` doesn't like difftimes, so convert to the natural units of some time types:
813
+
814
+ # ' @export
815
+ guess_period.Date <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
816
+ as.numeric(NextMethod(), units = " days" )
817
+ }
818
+
819
+ # ' @export
820
+ guess_period.POSIXt <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
821
+ as.numeric(NextMethod(), units = " secs" )
796
822
}
0 commit comments