1#' @include timespans.r 2#' @include util.r 3#' @include durations.r 4NULL 5 6check_period <- function(object) { 7 errors <- character() 8 9 length(object@.Data) -> n 10 lengths <- c(length(object@year), length(object@month), 11 length(object@day), length(object@hour), length(object@minute)) 12 13 if (any(lengths != n)) { 14 msg <- paste("Inconsistent lengths: year = ", lengths[1], 15 ", month = ", lengths[2], 16 ", day = ", lengths[3], 17 ", hour = ", lengths[4], 18 ", minute = ", lengths[5], 19 ", second = ", n, 20 sep = "") 21 errors <- c(errors, msg) 22 } 23 24 values <- c(object@year, object@month, object@day, object@hour, object@minute) 25 values <- na.omit(values) 26 if (sum(values - trunc(values))) { 27 msg <- "periods must have integer values" 28 errors <- c(errors, msg) 29 } 30 31 if (length(errors) == 0) 32 TRUE 33 else 34 errors 35} 36 37#' Period class 38#' 39#' Period is an S4 class that extends the [Timespan-class] class. 40#' Periods track the change in the "clock time" between two date-times. They 41#' are measured in common time related units: years, months, days, hours, 42#' minutes, and seconds. Each unit except for seconds must be expressed in 43#' integer values. 44#' 45#' The exact length of a period is not defined until the period is placed at a 46#' specific moment of time. This is because the precise length of one year, 47#' month, day, etc. can change depending on when it occurs due to daylight savings, 48#' leap years, and other conventions. A period can be 49#' associated with a specific moment in time by coercing it to an 50#' [Interval-class] object with [as.interval()] or by adding 51#' it to a date-time with "+". 52#' 53#' Periods provide a method for measuring generalized timespans when we wish to 54#' model clock times. Periods will attain intuitive results at this task even 55#' when leap years, leap seconds, gregorian days, daylight savings changes, and 56#' other events happen during the period. 57#' 58#' Because Period represents imprecise amount of time it cannot be compared to 59#' precise timestamps as Durations and Intervals are. You need to explicitely 60#' convert to durations. See [Duration-class]. 61#' 62#' The logic that guides arithmetic with periods can be unintuitive. Starting 63#' with version 1.3.0, \pkg{lubridate} enforces the reversible property of arithmetic 64#' (e.g. a date + period - period = date) by returning an NA if you create an 65#' implausible date by adding periods with months or years units to a date. For 66#' example, adding one month to January 31st, 2013 results in February 31st, 67#' 2013, which is not a real date. \pkg{lubridate} users have argued in the past that 68#' February 31st, 2013 should be rolled over to March 3rd, 2013 or rolled back 69#' to February 28, 2013. However, each of these corrections would destroy the 70#' reversibility of addition (Mar 3 - one month == Feb 3 != Jan 31, Feb 28 - one 71#' month == Jan 28 != Jan 31). If you would like to add and subtract months in a 72#' way that rolls the results back to the last day of a month (when appropriate) 73#' use the special operators, \code{\link{\%m+\%}}, \code{\link{\%m-\%}} or a 74#' bit more flexible [add_with_rollback()]. 75#' 76#' Period class objects have six slots. 1) .Data, a numeric object. The 77#' apparent amount of seconds to add to the period. 2) minute, a numeric object. 78#' The apparent amount of minutes to add to the period. 3) hour, a numeric object. 79#' The apparent amount of hours to add to the period.4) day, a numeric object. 80#' The apparent amount of days to add to the period.5) month, a numeric object. 81#' The apparent amount of months to add to the period. 6) year, a numeric object. 82#' The apparent amount of years to add to the period. 83#' 84#' @export 85#' @keywords internal 86setClass("Period", contains = c("Timespan", "numeric"), 87 slots = c(year = "numeric", month = "numeric", day = "numeric", 88 hour = "numeric", minute = "numeric"), 89 prototype = prototype(year = 0, month = 0, day = 0, hour = 0, minute = 0), 90 validity = check_period) 91 92#' @name hidden_aliases 93#' @aliases Arith,ANY,Period-method Arith,Duration,Period-method 94#' Arith,Period,Duration-method Compare,Period,Duration-method 95#' Compare,numeric,Period-method Compare,difftime,Period-method 96#' Compare,Period,difftime-method Compare,Period,Period-method 97#' Compare,Period,character-method Compare,Period,numeric-method 98#' Compare,character,Period-method second,Period-method second<-,Period-method 99#' minute,Period-method minute<-,Period-method hour,Period-method 100#' hour<-,Period-method Arith,Period,ANY-method day,Period-method 101#' day<-,Period-method month,Period-method month<-,Period-method 102#' year,Period-method year<-,Period-method date,Period-method 103#' date<-,Period-method as.numeric,Period-method show,Period-method 104#' c,Period-method rep,Period-method [,Period-method 105#' [<-,Period,ANY,ANY,Period-method [[,Period-method 106#' [[<-,Period,ANY,ANY,Period-method $,Period-method $<-,Period-method 107#' as.difftime,Period-method as.character,Period-method 108#' +,Period,Duration-method +,Period,Interval-method +,Period,Period-method 109#' +,Period,Date-method +,Date,Period-method +,Period,difftime-method 110#' +,difftime,Period-method +,Period,numeric-method +,numeric,Period-method 111#' +,Period,POSIXct-method +,POSIXct,Period-method +,Period,POSIXlt-method 112#' +,POSIXlt,Period-method /,Period,Duration-method /,Period,Interval-method 113#' /,Period,Period-method /,Period,difftime-method /,difftime,Period-method 114#' /,Period,numeric-method /,numeric,Period-method *,Period,ANY-method 115#' *,ANY,Period-method -,Period,ANY-method -,Period,missing-method 116#' -,ANY,Period-method -,Period,Period-method %%,Period,Duration-method 117#' %%,Period,Interval-method %%,Period,Period-method >,Period,Period-method 118#' >=,Period,Period-method ==,Period,Period-method !=,Period,Period-method 119#' <=,Period,Period-method <,Period,Period-method >,Period,Duration-method 120#' >=,Period,Duration-method ==,Period,Duration-method 121#' !=,Period,Duration-method <=,Period,Duration-method 122#' <,Period,Duration-method >,Duration,Period-method >=,Duration,Period-method 123#' ==,Duration,Period-method !=,Duration,Period-method 124#' <=,Duration,Period-method <,Duration,Period-method >,Period,numeric-method 125#' >=,Period,numeric-method ==,Period,numeric-method !=,Period,numeric-method 126#' <=,Period,numeric-method <,Period,numeric-method >,numeric,Period-method 127#' >=,numeric,Period-method ==,numeric,Period-method !=,numeric,Period-method 128#' <=,numeric,Period-method <,numeric,Period-method !=,Duration,Period 129#' !=,Period,Duration !=,Period,Period !=,Period,numeric !=,numeric,Period 130#' %%,Period,Duration %%,Period,Interval %%,Period,Period *,ANY,Period 131#' *,Period,ANY -,ANY,Period -,Period,Interval -,Period,missing 132#' /,numeric,Period <,Duration,Period <,Period,Duration <,Period,Period 133#' <,Period,numeric <,numeric,Period <=,Duration,Period <=,Period,Duration 134#' <=,Period,Period <=,Period,numeric <=,numeric,Period ==,Duration,Period 135#' ==,Period,Duration ==,Period,Period ==,Period,numeric ==,numeric,Period 136#' >,Duration,Period >,Period,Duration >,Period,Period >,Period,numeric 137#' >,numeric,Period >=,Duration,Period >=,Period,Duration >=,Period,Period 138#' >=,Period,numeric >=,numeric,Period 139NULL 140 141setMethod("initialize", "Period", function(.Object, ...) { 142 dots <- list(...) 143 names(dots)[!nzchar(allNames(dots))] <- ".Data" 144 lens <- unlist(lapply(dots, length), F, F) 145 146 ## if any 0-length components, the entire object is 0-length 147 if (any(lens == 0)) { 148 for (nm in slotNames(.Object)) 149 slot(.Object, nm) <- numeric() 150 validObject(.Object) 151 return(.Object) 152 } 153 154 len <- max(lens) 155 nas <- FALSE 156 for (nm in slotNames(.Object)) { 157 el <- 158 if (is.null(obj <- dots[[nm]])) { 159 rep.int(0L, len) 160 } else { 161 if (length(obj) < len) rep_len(obj, len) 162 else obj 163 } 164 nas <- nas | is.na(el) 165 slot(.Object, nm) <- el 166 } 167 168 ## If any component has NAs the entire object should have those NAs 169 if (any(nas)) { 170 for (nm in slotNames(.Object)) { 171 slot(.Object, nm)[nas] <- NA_real_ 172 } 173 } 174 175 validObject(.Object) 176 .Object 177}) 178 179#' @export 180setMethod("show", signature(object = "Period"), function(object) { 181 if (length(object@.Data) == 0) { 182 cat("<Period[0]>\n") 183 } else { 184 print(format(object)) 185 } 186}) 187 188#' @export 189format.Period <- function(x, ...) { 190 if (length(x) == 0) { 191 return(character()) 192 } 193 194 show <- paste( 195 x@year, "y ", x@month, "m ", x@day, "d ", 196 x@hour, "H ", x@minute, "M ", x@.Data, "S", 197 sep = "" 198 ) 199 start <- regexpr("[-1-9]|(0\\.)", show) 200 show <- ifelse(start > 0, substr(show, start, nchar(show)), "0S") 201 202 show[is.na(x)] <- NA 203 show 204} 205 206#' @export 207xtfrm.Period <- function(x) { 208 xtfrm(period_to_seconds(x)) 209} 210 211#' @export 212setMethod("c", signature(x = "Period"), function(x, ...) { 213 dots <- list(...) 214 nempty <- sapply(dots, length) != 0 215 elements <- lapply(dots[nempty], as.period) 216 seconds <- c(x@.Data, unlist(lapply(elements, slot, ".Data"))) 217 years <- c(x@year, unlist(lapply(elements, slot, "year"))) 218 months <- c(x@month, unlist(lapply(elements, slot, "month"))) 219 days <- c(x@day, unlist(lapply(elements, slot, "day"))) 220 hours <- c(x@hour, unlist(lapply(elements, slot, "hour"))) 221 minutes <- c(x@minute, unlist(lapply(elements, slot, "minute"))) 222 new("Period", seconds, year = years, month = months, day = days, 223 hour = hours, minute = minutes) 224}) 225 226#' @export 227setMethod("rep", signature(x = "Period"), function(x, ...) { 228 new("Period", rep(x@.Data, ...), year = rep(x@year, ...), 229 month = rep(x@month, ...), day = rep(x@day, ...), 230 hour = rep(x@hour, ...), minute = rep(x@minute, ...)) 231}) 232 233#' @export 234setMethod("[", signature(x = "Period"), 235 function(x, i, j, ..., drop = TRUE) { 236 new("Period", x@.Data[i], year = x@year[i], month = x@month[i], 237 day = x@day[i], hour = x@hour[i], minute = x@minute[i]) 238}) 239 240#' @export 241setMethod("[[", signature(x = "Period"), 242 function(x, i, j, ..., exact = TRUE) { 243 new("Period", x@.Data[i], year = x@year[i], month = x@month[i], 244 day = x@day[i], hour = x@hour[i], minute = x@minute[i]) 245}) 246 247#' @export 248setMethod("[<-", signature(x = "Period", value = "Period"), 249 function(x, i, j, ..., value) { 250 x@.Data[i] <- value@.Data 251 x@year[i] <- value@year 252 x@month[i] <- value@month 253 x@day[i] <- value@day 254 x@hour[i] <- value@hour 255 x@minute[i] <- value@minute 256 x 257}) 258 259#' @export 260setMethod("[[<-", signature(x = "Period", value = "Period"), 261 function(x, i, j, ..., value) { 262 x@.Data[i] <- value@.Data 263 x@year[i] <- value@year 264 x@month[i] <- value@month 265 x@day[i] <- value@day 266 x@hour[i] <- value@hour 267 x@minute[i] <- value@minute 268 x 269}) 270 271#' @export 272setMethod("$", signature(x = "Period"), function(x, name) { 273 if (name == "second") name <- ".Data" 274 slot(x, name) 275}) 276 277#' @export 278setMethod("$<-", signature(x = "Period"), function(x, name, value) { 279 if (name == "second") name <- ".Data" 280 slot(x, name) <- rep_len(value, length(x)) 281 x 282}) 283 284#' Create or parse period objects 285#' 286#' `period()` creates or parses a period object with the specified values. 287#' 288#' Within a Period object, time units do not have a fixed length (except for 289#' seconds) until they are added to a date-time. The length of each time unit 290#' will depend on the date-time to which it is added. For example, a year that 291#' begins on 2009-01-01 will be 365 days long. A year that begins on 2012-01-01 292#' will be 366 days long. When math is performed with a period object, each unit 293#' is applied separately. How the length of a period is distributed among its 294#' units is non-trivial. For example, when leap seconds occur 1 minute is longer 295#' than 60 seconds. 296#' 297#' Periods track the change in the "clock time" between two date-times. They 298#' are measured in common time related units: years, months, days, hours, 299#' minutes, and seconds. Each unit except for seconds must be expressed in 300#' integer values. 301#' 302#' Besides the main constructor and parser [period()], period objects can also 303#' be created with the specialized functions [years()], [months()], [weeks()], 304#' [days()], [hours()], [minutes()], and [seconds()]. These objects can be added 305#' to and subtracted to date-times to create a user interface similar to object 306#' oriented programming. 307#' 308#' Note: Arithmetic with periods can result in undefined behavior when 309#' non-existent dates are involved (such as February 29th in non-leap years). 310#' Please see [Period-class] for more details and \code{\link{\%m+\%}} and 311#' [add_with_rollback()] for alternative operations. 312#' 313#' @name period 314#' @aliases periods 315#' @param num a numeric or character vector. A character vector can specify 316#' periods in a convenient shorthand format or ISO 8601 specification. All 317#' unambiguous name units and abbreviations are supported, "m" stands for 318#' months, "M" for minutes unless ISO 8601 "P" modifier is present (see 319#' examples). Fractional units are supported but the fractional part is always 320#' converted to seconds. 321#' @param units a character vector that lists the type of units to be used. The 322#' units in units are matched to the values in num according to their 323#' order. When `num` is character, this argument is ignored. 324#' @param ... a list of time units to be included in the period and their 325#' amounts. Seconds, minutes, hours, days, weeks, months, and years are 326#' supported. Normally only one of `num` or `...` are present. If both are 327#' present, the periods are concatenated. 328#' @param x Any R object for `is.periods` and a numeric value of the number of 329#' units for elementary constructors. With the exception of seconds(), x must 330#' be an integer. 331#' @param abbreviate Ignored. For consistency with S3 generic in base namespace. 332#' @seealso [Period-class], [period()], \code{\link{\%m+\%}}, 333#' [add_with_rollback()] 334#' @return a period object 335#' @keywords chron classes 336#' @examples 337#' 338#' ### Separate period and units vectors 339#' 340#' period(c(90, 5), c("second", "minute")) 341#' # "5M 90S" 342#' period(-1, "days") 343#' period(c(3, 1, 2, 13, 1), c("second", "minute", "hour", "day", "week")) 344#' period(c(1, -60), c("hour", "minute")) 345#' period(0, "second") 346#' 347#' ### Units as arguments 348#' 349#' period (second = 90, minute = 5) 350#' period(day = -1) 351#' period(second = 3, minute = 1, hour = 2, day = 13, week = 1) 352#' period(hour = 1, minute = -60) 353#' period(second = 0) 354#' period(c(1, -60), c("hour", "minute"), hour = c(1, 2), minute = c(3, 4)) 355#' 356#' ### Lubridate style parsing 357#' 358#' period("2M 1sec") 359#' period("2hours 2minutes 1second") 360#' period("2d 2H 2M 2S") 361#' period("2days 2hours 2mins 2secs") 362#' period("2 days, 2 hours, 2 mins, 2 secs") 363#' # Missing numerals default to 1. Repeated units are added up. 364#' duration("day day") 365#' 366#' ### ISO 8601 parsing 367#' 368#' period("P10M23DT23H") # M stands for months 369#' period("10DT10M") # M stands for minutes 370#' period("P3Y6M4DT12H30M5S") # M for both minutes and months 371#' period("P23DT60H 20min 100 sec") # mixing ISO and lubridate style parsing 372#' 373#' ### Comparison with characters (from v1.6.0) 374#' 375#' duration("day 2 sec") > "day 1sec" 376#' 377#' ### Elementary Constructors 378#' 379#' x <- ymd("2009-08-03") 380#' x + days(1) + hours(6) + minutes(30) 381#' x + days(100) - hours(8) 382#' 383#' class(as.Date("2009-08-09") + days(1)) # retains Date class 384#' as.Date("2009-08-09") + hours(12) 385#' class(as.Date("2009-08-09") + hours(12)) 386#' # converts to POSIXt class to accomodate time units 387#' 388#' years(1) - months(7) 389#' c(1:3) * hours(1) 390#' hours(1:3) 391#' 392#' # sequencing 393#' y <- ymd(090101) # "2009-01-01 CST" 394#' y + months(0:11) 395#' 396#' # compare DST handling to durations 397#' boundary <- ymd_hms("2009-03-08 01:59:59", tz="America/Chicago") 398#' boundary + days(1) # period 399#' boundary + ddays(1) # duration 400#' @export 401period <- function(num = NULL, units = "second", ...) { 402 if (is.character(num)) { 403 parse_period(num) 404 } else { 405 out1 <- .period_from_num(num, units) 406 out2 <- .period_from_units(list(...)) 407 if (is.null(out1) && is.null(out2)) new("Period", numeric()) 408 else if (is.null(out1)) out2 409 else if (is.null(out2)) out1 410 else c(out1, out2) 411 } 412} 413 414parse_period <- function(x) { 415 out <- .Call(C_parse_period, as.character(x)) 416 new("Period", 417 out[1, ], 418 minute = out[2, ], 419 hour = out[3, ], 420 day = out[4, ] + 7L*out[5, ], 421 month = out[6, ], 422 year = out[7, ]) 423} 424 425.period_from_num <- function(num, units) { 426 if (length(num) == 0) 427 return(NULL) 428 429 if (!is.numeric(num)) { 430 stop(sprintf("First argument to `period()` constructor must be character or numeric. Supplied object of class '%s'", class(num))) 431 } 432 433 ## qucik check for common wrongdoings: #462 434 if (inherits(num, c("Interval", "Duration"))) 435 stop("Interval or Durations objects cannot be used as input to 'period()' constructor. Plese use 'as.period()'.") 436 437 if (length(units) %% length(num) != 0) 438 stop("Arguments `num` and `units` must have same length") 439 440 .period_from_units(structure(num, names = units)) 441} 442 443.period_from_units <- function(pieces) { 444 if (length(pieces) == 0) 445 return(NULL) 446 447 if (!is.numeric(pieces)) 448 pieces <- lapply(pieces, as.numeric) 449 450 out <- list(second = 0, minute = 0, hour = 0, day = 0, 451 week = 0, month = 0, year = 0) 452 453 unit <- standardise_date_names(names(pieces)) 454 for (i in seq_along(unit)) { 455 nm <- unit[[i]] 456 out[[nm]] <- out[[nm]] + pieces[[i]] 457 } 458 out$day <- out$day + 7 * out$week 459 460 new("Period", out$second, year = out$year, month = out$month, 461 day = out$day, hour = out$hour, minute = out$minute) 462} 463 464#' @rdname period 465#' @examples 466#' is.period(as.Date("2009-08-03")) # FALSE 467#' is.period(period(months= 1, days = 15)) # TRUE 468#' @export 469is.period <- function(x) is(x, "Period") 470 471#' @export seconds minutes hours days weeks years milliseconds microseconds microseconds nanoseconds picoseconds 472#' @rdname period 473seconds <- function(x = 1) period(second = x) 474#' @rdname period 475minutes <- function(x = 1) period(minute = x) 476#' @rdname period 477hours <- function(x = 1) period(hour = x) 478#' @rdname period 479days <- function(x = 1) period(day = x) 480#' @rdname period 481weeks <- function(x = 1) period(week = x) 482#' @rdname period 483years <- function(x = 1) period(year = x) 484#' @rdname period 485milliseconds <- function(x = 1) seconds(x/1000) 486#' @rdname period 487microseconds <- function(x = 1) seconds(x/1000000) 488#' @rdname period 489nanoseconds <- function(x = 1) seconds(x/1e9) 490#' @rdname period 491picoseconds <- function(x = 1) seconds(x/1e12) 492 493#' @rdname period 494#' @export 495months.numeric <- function(x, abbreviate) { 496 period(month = x) 497} 498 499#' Contrive a period to/from a given number of seconds 500#' 501#' `period_to_seconds()` approximately converts a period to seconds assuming 502#' there are 365.25 days in a calendar year and 365.25/12 days in a month. 503#' 504#' @param x A numeric object. The number of seconds to coerce into a period. 505#' @return A number (period) that roughly equates to the period (seconds) given. 506#' @export 507period_to_seconds <- function(x) { 508 x@.Data + 509 60 * x@minute + 510 60 * 60 * x@hour + 511 60 * 60 * 24 * x@day + 512 60 * 60 * 24 * 365.25 / 12 * x@month + 513 60 * 60 * 24 * 365.25 * x@year 514} 515 516#' @description 517#' `seconds_to_period()` create a period that has the maximum number of 518#' non-zero elements (days, hours, minutes, seconds). This computation is exact 519#' because it doesn't involve years or months. 520#' @rdname period_to_seconds 521#' @export 522seconds_to_period <- function(x) { 523 span <- as.double(x) 524 remainder <- abs(span) 525 newper <- period(second = rep(0, length(x))) 526 527 slot(newper, "day") <- remainder %/% (3600 * 24) 528 remainder <- remainder %% (3600 * 24) 529 530 slot(newper, "hour") <- remainder %/% (3600) 531 remainder <- remainder %% (3600) 532 533 slot(newper, "minute") <- remainder %/% (60) 534 535 slot(newper, ".Data") <- remainder %% (60) 536 537 newper * sign(span) 538} 539 540#' @export 541summary.Period <- function(object, ...) { 542 nas <- is.na(object) 543 object <- object[!nas] 544 persecs <- period_to_seconds(object) 545 qq <- stats::quantile(persecs) 546 qq <- c(qq[1L:3L], mean(persecs), qq[4L:5L]) 547 qq <- seconds_to_period(qq) 548 qq <- as.character(qq) 549 names(qq) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", 550 "Max.") 551 if (any(nas)) 552 c(qq, `NA's` = sum(nas)) 553 else qq 554} 555 556#' @export 557setMethod("Arith", signature(e1 = "Period", e2 = "ANY"), function(e1, e2) { 558 stop_incompatible_classes(e1, e2, .Generic) 559}) 560 561#' @export 562setMethod("Arith", signature(e1 = "ANY", e2 = "Period"), function(e1, e2) { 563 stop_incompatible_classes(e1, e2, .Generic) 564}) 565 566## duration is.numeric. So we need these explicits here: 567#' @export 568setMethod("Arith", signature(e1 = "Duration", e2 = "Period"), function(e1, e2) { 569 stop_incompatible_classes(e1, e2, .Generic) 570}) 571 572#' @export 573setMethod("Arith", signature(e1 = "Period", e2 = "Duration"), function(e1, e2) { 574 stop_incompatible_classes(e1, e2, .Generic) 575}) 576 577#' @export 578setMethod("Compare", signature(e1 = "Period", e2 = "Period"), 579 function(e1, e2) { 580 callGeneric(period_to_seconds(e1), period_to_seconds(e2)) 581 }) 582 583#' @export 584setMethod("Compare", signature(e1 = "Period", e2 = "character"), 585 function(e1, e2) { 586 callGeneric(e1, as.period(e2)) 587 }) 588 589#' @export 590setMethod("Compare", signature(e1 = "character", e2 = "Period"), 591 function(e1, e2) { 592 callGeneric(as.period(e1), e2) 593 }) 594 595#' @export 596setMethod("Compare", signature(e1 = "Period", e2 = "Duration"), 597 function(e1, e2) { 598 callGeneric(as.duration(e1), e2) 599 }) 600 601#' @export 602setMethod("Compare", signature(e1 = "Duration", e2 = "Period"), 603 function(e1, e2) { 604 callGeneric(e1, as.duration(e2)) 605 }) 606 607#' @export 608setMethod("Compare", signature(e1 = "Period", e2 = "numeric"), 609 function(e1, e2) { 610 callGeneric(as.numeric(e1, "secs"), e2) 611 }) 612 613#' @export 614setMethod("Compare", signature(e1 = "numeric", e2 = "Period"), 615 function(e1, e2) { 616 callGeneric(e1, as.numeric(e2, "secs")) 617 }) 618 619#' @export 620setMethod("Compare", c(e1 = "Period", e2 = "difftime"), 621 function(e1, e2) { 622 callGeneric(as.numeric(e1, units = "secs"), as.numeric(e2, units = "secs")) 623 }) 624 625#' @export 626setMethod("Compare", c(e1 = "difftime", e2 = "Period"), 627 function(e1, e2) { 628 callGeneric(as.numeric(e1, units = "secs"), as.numeric(e2, units = "secs")) 629 }) 630