@@ -670,28 +670,52 @@ gcd_num <- function(dividends, ..., rrtol = 1e-6, pqlim = 1e6, irtol = 1e-6) {
670
670
vctrs :: vec_cast(numeric_gcd , dividends )
671
671
}
672
672
673
- # ' Use max valid period as guess for `period` of `ref_time_values`
674
- # '
675
- # ' @param ref_time_values Vector containing time-interval-like or time-like
676
- # ' data, with at least two distinct values, [`diff`]-able (e.g., a
677
- # ' `time_value` or `version` column), and should have a sensible result from
678
- # ' adding `is.numeric` versions of its `diff` result (via `as.integer` if its
679
- # ' `typeof` is `"integer"`, otherwise via `as.numeric`).
680
- # ' @param ref_time_values_arg Optional, string; name to give `ref_time_values`
681
- # ' in error messages. Defaults to quoting the expression the caller fed into
682
- # ' the `ref_time_values` argument.
683
- # ' @return `is.numeric`, length 1; attempts to match `typeof(ref_time_values)`
684
- guess_period <- function (ref_time_values , ref_time_values_arg = rlang :: caller_arg(ref_time_values )) {
685
- sorted_distinct_ref_time_values <- sort(unique(ref_time_values ))
686
- if (length(sorted_distinct_ref_time_values ) < 2L ) {
687
- cli_abort(" Not enough distinct values in {.code {ref_time_values_arg}} to guess the period." , ref_time_values_arg )
673
+ # ' Use max valid period as guess for `period` of `time_values`
674
+ # '
675
+ # ' `r lifecycle::badge("experimental")`
676
+ # '
677
+ # ' @param time_values Vector containing time-interval-like or time-point-like
678
+ # ' data, with at least two distinct values.
679
+ # ' @param time_values_arg Optional, string; name to give `time_values` in error
680
+ # ' messages. Defaults to quoting the expression the caller fed into the
681
+ # ' `time_values` argument.
682
+ # ' @return length-1 vector; `r lifecycle::badge("experimental")` class will
683
+ # ' either be the same class as [`base::diff()`] on such time values, an
684
+ # ' integer, or a double, such that all `time_values` can be exactly obtained
685
+ # ' by adding `k * result` for an integer k, and such that there is no smaller
686
+ # ' `result` that can achieve this.
687
+ # ' @export
688
+ guess_period <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
689
+ UseMethod(" guess_period" )
690
+ }
691
+
692
+ # ' @export
693
+ guess_period.default <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
694
+ rlang :: check_dots_empty()
695
+ sorted_distinct_time_values <- sort(unique(time_values ))
696
+ if (length(sorted_distinct_time_values ) < 2L ) {
697
+ cli_abort(" Not enough distinct values in {.code {time_values_arg}} to guess the period." ,
698
+ class = " epiprocess__guess_period__not_enough_times" ,
699
+ time_values = time_values
700
+ )
688
701
}
689
- skips <- diff(sorted_distinct_ref_time_values )
690
- decayed_skips <-
691
- if (typeof(skips ) == " integer" ) {
692
- as.integer(skips )
693
- } else {
694
- as.numeric(skips )
695
- }
696
- gcd_num(decayed_skips )
702
+ skips <- diff(sorted_distinct_time_values )
703
+ # Certain diff results have special classes or attributes; use vctrs to try to
704
+ # appropriately destructure for gcd_num, then restore to their original class
705
+ # & attributes.
706
+ skips_data <- vctrs :: vec_data(skips )
707
+ period_data <- gcd_num(skips_data , rrtol = 0 )
708
+ vctrs :: vec_restore(period_data , skips )
709
+ }
710
+
711
+ # `full_seq()` doesn't like difftimes, so convert to the natural units of some time types:
712
+
713
+ # ' @export
714
+ guess_period.Date <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
715
+ as.numeric(NextMethod(), units = " days" )
716
+ }
717
+
718
+ # ' @export
719
+ guess_period.POSIXt <- function (time_values , time_values_arg = rlang :: caller_arg(time_values ), ... ) {
720
+ as.numeric(NextMethod(), units = " secs" )
697
721
}
0 commit comments