1#' @include timespans.r
2#' @include durations.r
3#' @include intervals.r
4#' @include periods.r
5
6
7setOldClass("difftime")
8
9#' Create a difftime object.
10#'
11#' `make_difftime()` creates a difftime object with the specified number of
12#' units. Entries for different units are cumulative. difftime displays
13#' durations in various units,  but these units are estimates given for
14#' convenience. The underlying object is always recorded as a fixed number of
15#' seconds.
16#'
17#' Conceptually, difftime objects are a type of duration. They measure the
18#' exact passage of time but do not always align with measurements
19#' made in larger units of time such as hours, months and years.
20#' This is because the length of larger time units can be affected
21#' by conventions such as leap years
22#' and Daylight Savings Time. \pkg{lubridate} provides a second class for measuring durations, the Duration class.
23#' @param num Optional number of seconds
24#' @param units a character vector that lists the type of units to use for the
25#'   display of the return value (see examples). If `units` is "auto" (the
26#'   default) the display units are computed automatically. This might create
27#'   undesirable effects when converting `difftime` objects to numeric
28#'   values in data processing.
29#' @param ... a list of time units to be included in the difftime and their amounts. Seconds,
30#'   minutes, hours, days, and weeks are supported. Normally only one of `num` or `...` are present. If
31#'   both are present, the `difftime` objects are concatenated.
32#' @return a difftime object
33#' @seealso [duration()], [as.duration()]
34#' @keywords chron classes
35#' @export
36#' @examples
37#' make_difftime(1)
38#' make_difftime(60)
39#' make_difftime(3600)
40#' make_difftime(3600, units = "minute")
41#' # Time difference of 60 mins
42#' make_difftime(second = 90)
43#' # Time difference of 1.5 mins
44#' make_difftime(minute = 1.5)
45#' # Time difference of 1.5 mins
46#' make_difftime(second = 3, minute = 1.5, hour = 2, day = 6, week = 1)
47#' # Time difference of 13.08441 days
48#' make_difftime(hour = 1, minute = -60)
49#' # Time difference of 0 secs
50#' make_difftime(day = -1)
51#' # Time difference of -1 days
52#' make_difftime(120, day = -1, units = "minute")
53#' # Time differences in mins
54make_difftime <- function(num = NULL, units = "auto", ...) {
55  pieces <- list(...)
56  if (!is.null(num) && length(pieces) > 0) {
57    .difftime_from_num(c(num, .difftime_from_pieces(pieces)), units)
58  } else if (!is.null(num)) {
59    .difftime_from_num(num, units)
60  } else if (length(pieces)) {
61    .difftime_from_num(.difftime_from_pieces(pieces), units)
62  } else {
63    stop("No valid values have been passed to 'make_difftime' constructor")
64  }
65}
66
67difftime_lengths <- c(secs = 1, mins = 60, hours = 3600, days = 86400, weeks = 7 * 86400)
68
69.difftime_from_num <- function(num, units = "auto") {
70  seconds <- abs(na.omit(num))
71  units <- units[[1]]
72  if (units == "auto") {
73    if (any(seconds < 60))
74      units <- "secs"
75    else if (any(seconds < 3600))
76      units <- "mins"
77    else if (any(seconds < 86400))
78      units <- "hours"
79    else
80      units <- "days"
81  } else {
82    units <- standardise_difftime_names(units)
83  }
84  structure(num/difftime_lengths[[units]], units = units, class = "difftime")
85}
86
87.difftime_from_pieces <- function(pieces) {
88  names(pieces) <- standardise_difftime_names(names(pieces))
89  out <- 0
90  for (nm in names(pieces))
91    out <- out + pieces[[nm]] * difftime_lengths[[nm]]
92  out
93}
94
95#' Is x a difftime object?
96#'
97#' @export is.difftime
98#' @param x an R object
99#' @return TRUE if x is a difftime object, FALSE otherwise.
100#' @seealso [is.instant()], [is.timespan()], [is.interval()],
101#'   [is.period()].
102#' @keywords logic chron
103#' @examples
104#' is.difftime(as.Date("2009-08-03")) # FALSE
105#' is.difftime(make_difftime(days = 12.4)) # TRUE
106is.difftime <- function(x) is(x, "difftime")
107