R/year.R

Defines functions .new_year Ops.grates_year quantile.grates_year Math.grates_year Summary.grates_year range.grates_year max.grates_year min.grates_year as.list.grates_year as.character.grates_year as.POSIXlt.grates_year as.POSIXct.grates_year as.Date.grates_year as.double.grates_year as.integer.grates_year seq.grates_year c.grates_year unique.grates_year rep.grates_year `[<-.grates_year` `[[.grates_year` `[.grates_year` as_year.factor as_year.character as_year.POSIXt as_year.Date as_year.default as_year vec_ptype_full.grates_year vec_ptype_abbr.grates_year format.grates_year print.grates_year is_year year

Documented in as_year as_year.character as_year.Date as_year.default as_year.factor as_year.POSIXt format.grates_year is_year print.grates_year year

# -------------------------------------------------------------------------
#' Construct a year object
#'
# -------------------------------------------------------------------------
#' `year()` is a constructor for `<grates_year>` objects.
#'
# -------------------------------------------------------------------------
#' @param x `[integer]`
#'
#' Vector representing the years.
#'
#' `double` vectors will be converted via `as.integer(floor(x))`.
#'
#' @param object
#'
#' \R object.
#'
# -------------------------------------------------------------------------
#' @return
#' A `<grates_year>` object.
#'
# -------------------------------------------------------------------------
#' @examples
#' year(2011:2020)
#'
# -------------------------------------------------------------------------
#' @export
year <- function(x = integer()) {
    if (!is.integer(x)) {
        if (is.vector(x, "double")) {
            x <- as.integer(floor(x))
        } else {
            stop("`x` must be integer.")
        }
    }

    .new_year(x = x)
}

# -------------------------------------------------------------------------
#' @rdname year
#' @export
is_year <- function(object) {
    inherits(object, "grates_year")
}

# -------------------------------------------------------------------------
#' Print a year-quarter object
#'
#' @param x A `<grates_year>` object.
#' @param ... Not currently used.
#'
#' @export
print.grates_year <- function(x, ...) {
    # replicate the header as in vctrs
    n <- length(x)
    cat("<grates_year[", n, "]>\n", sep="")
    if (n)
        print(as.integer(x))
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname print.grates_year
#' @export
format.grates_year <- function(x, ...) {
    if (length(x) == 0)
        return(character(0))
    class(x) <- NULL
    out <- as.character(x)
    out[is.na(x)] <- NA_character_
    out
}

# -------------------------------------------------------------------------
vec_ptype_abbr.grates_year <- function(x, ...) {"year"}
vec_ptype_full.grates_year <- function(x, ...) {"grates_year"}

# -------------------------------------------------------------------------
#' Coerce an object to year-quarter
#'
# -------------------------------------------------------------------------
#' `as_year()` is a generic for coercing input in to `<grates_year>`.
#'
# -------------------------------------------------------------------------
#' @param x \R object.
#'
#' Character input is first parsed using `as.Date()`.
#'
#' POSIXct and POSIXlt are converted with the timezone respected.
#'
#' @param ...
#'
#' Only used For character input where additional arguments are passed through
#' to `as.Date()`.
#'
# -------------------------------------------------------------------------
#' @return
#' A `<grates_year>` object.
#'
# -------------------------------------------------------------------------
#' @examples
#' as_year(Sys.Date())
#' as_year(as.POSIXct("2019-03-04 01:01:01", tz = "America/New_York"), interval = 2)
#' as_year("2019-05-03")
#'
# -------------------------------------------------------------------------
#' @seealso
#' `as.Date()`
#'
# -------------------------------------------------------------------------
#' @export
as_year <- function(x, ...) {
    UseMethod("as_year")
}

# -------------------------------------------------------------------------
#' @rdname as_year
#' @export
as_year.default <- function(x, ...) {
    stopf("Not implemented for class [%s].", paste(class(x), collapse = ", "))
}

# -------------------------------------------------------------------------
#' @rdname as_year
#' @export
as_year.Date <- function(x, ...) {

    # convert to posixlt (this will always be UTC when called on a date)
    x <- as.POSIXlt(x)

    # calculate the year
    .new_year(x$year + 1900L)
}

# -------------------------------------------------------------------------
#' @rdname as_year
#' @export
as_year.POSIXt <- function(x, ...) {
    x <- .as_date(x)
    as_year.Date(x)
}

# -------------------------------------------------------------------------
#' @rdname as_year
#' @export
as_year.character <- function(x, ...) {
    out <- as.Date(x, ...)
    if (all(is.na(out)))
        stop("Unable to parse any entries of `x` as Dates.")
    as_year.Date(x = out, ...)
}

# -------------------------------------------------------------------------
#' @rdname as_year
#' @export
as_year.factor <- function(x, ...) {
    x <- as.character(x)
    as_year.character(x, ...)
}

#' @export
`[.grates_year` <- function(x, ..., drop = FALSE) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
`[[.grates_year` <- function(x, ..., drop = TRUE) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
`[<-.grates_year` <- function(x, ..., value) {
    if (!inherits(value, "grates_year"))
        stop("Can only assign <grates_year> objects in to an <grates_year> object.")
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
`[[<-.grates_year` <- `[<-.grates_year`

# -------------------------------------------------------------------------
#' @export
rep.grates_year <- function(x, ...) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
unique.grates_year <- function(x, incomparables = FALSE, ...) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
c.grates_year <- function(..., recursive = FALSE, use.names = TRUE) {
    dots <- list(...)
    if (!all(vapply(dots, inherits, TRUE, what = "grates_year")))
        stop("Unable to combine <grates_year> objects with other classes.")
    res <- NextMethod()
    .new_year(res)
}

# -------------------------------------------------------------------------
#' @export
seq.grates_year <- function(from, to, by = 1L, ...) {

    if (!inherits(to, "grates_year") || length(to) != 1L)
        stop("`to` must be a <grates_year> object of length 1.")

    if (!.is_scalar_whole(by))
        stop("`by` must be an integer of length 1.")

    from <- as.integer(from)
    to <- as.integer(to)
    out <- seq.int(from = from, to = to, by = by)

    # Ensure integer as we cannot rely on seq.int (may return double)
    out <- as.integer(out)
    .new_year(out)
}

# -------------------------------------------------------------------------
#' @export
as.integer.grates_year <- function(x, ...) {
    unclass(x)
}

# -------------------------------------------------------------------------
#' @export
as.double.grates_year <- function(x, ...) {
    as.double(unclass(x))
}

# -------------------------------------------------------------------------
#' @export
as.Date.grates_year <- function(x, ...) {
    days <- .month_to_days((unclass(x) - 1970L) * 12L)
    .Date(as.double(days))
}

# -------------------------------------------------------------------------
#' @export
as.POSIXct.grates_year <- function(x, tz = "UTC", ...) {
    if (tz != "UTC")
        stop("<grates_year> objects can only be converted to UTC. If other timezones are required, first convert to <Date> and then proceed as desired.")
    x <- .month_to_days((unclass(x) - 1970L) * 12L)
    .POSIXct(x * 86400, tz = "UTC")
}

# -------------------------------------------------------------------------
#' @export
as.POSIXlt.grates_year <- function(x, tz = "UTC", ...) {
    if (tz != "UTC")
        stop("<grates_year> objects can only be converted to UTC. If other timezones are required, first convert to <Date> and then proceed as desired.")
    x <- .month_to_days((unclass(x) - 1970L) * 12L)
    as.POSIXlt(x * 86400, tz = "UTC", origin = .POSIXct(0, tz = "UTC"))
}

# -------------------------------------------------------------------------
#' @export
as.character.grates_year <- function(x, ...) {
    format.grates_year(x)
}

# -------------------------------------------------------------------------
#' @export
as.list.grates_year <- function(x, ...) {
    lapply(unclass(x), `class<-`, class(x))
}

# -------------------------------------------------------------------------
#' @export
as.data.frame.grates_year <- as.data.frame.vector

# -------------------------------------------------------------------------
#' @export
min.grates_year <- function(x, ..., na.rm = FALSE) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
max.grates_year <- function(x, ..., na.rm = FALSE) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
range.grates_year <- function(x, ..., na.rm = FALSE) {
    out <- NextMethod()
    class(out) <- class(x)
    out
}

# -------------------------------------------------------------------------
#' @export
Summary.grates_year <- function(..., na.rm = FALSE) {
    stopf("`%s()` is not supported for <grates_year> objects.", .Generic)
}

# -------------------------------------------------------------------------
#' @export
Math.grates_year <- function(x, ...) {
    stopf("`%s()` is not supported for <grates_year> objects.", .Generic)
}

# -------------------------------------------------------------------------
#' @export
quantile.grates_year <- function(x, type = 1, ...) {
    x <- unclass(x)
    x <- as.integer(quantile(x, type = type, ...))
    .new_year(x)
}

# -------------------------------------------------------------------------
#' @export
Ops.grates_year <- function(e1, e2) {
    op <- .Generic
    if (op %in% c("==", "!=", "<", ">", "<=", ">=")) {
        if (!inherits(e2, "grates_year"))
            stop("Can only compare <grates_year> objects with <grates_year> objects.")
        return(NextMethod())
    }

    switch(
        op,
        "+" = {
            if (missing(e2)) {
                return(e1)
            } else if (inherits(e1, "grates_year") && inherits(e2, "grates_year")) {
                stop("Cannot add <grates_year> objects to each other.")
            } else if (inherits(e1, "grates_year") && (.is_whole(e2))) {
                .new_year(unclass(e1) + as.integer(e2))
            } else if (inherits(e2, "grates_year") && (.is_whole(e1))) {
                .new_year(unclass(e2) + as.integer(e1))
            } else {
                stop("Can only add integers to <grates_year> objects.")
            }
        },
        "-" = {
            if (missing(e2)) {
                stop("Cannot negate a <grates_year> object.")
            } else if (inherits(e2, "grates_year")) {
                if (!inherits(e1, "grates_year"))
                    stop("Can only subtract from a <grates_year> object, not vice-versa.")
                unclass(e1) - unclass(e2)
            } else if (inherits(e1, "grates_year") && is.integer(e2)) {
                .new_year(unclass(e1) - e2)
            } else if (inherits(e1, "grates_year") && .is_whole(e2)) {
                .new_year(unclass(e1) - as.integer(e2))
            } else {
                stop("Can only subtract whole numbers and other <grates_year> objects from <grates_year> objects.")
            }
        },
        stopf("%s is not compatible with <grates_year> objects.", op)
    )
}

# ------------------------------------------------------------------------- #
# ------------------------------------------------------------------------- #
# -------------------------------- INTERNALS ------------------------------ #
# ------------------------------------------------------------------------- #
# ------------------------------------------------------------------------- #

.new_year <- function(x = integer()) {
    structure(x, class = "grates_year")
}

Try the grates package in your browser

Any scripts or data that you put into this service are public.

grates documentation built on July 9, 2023, 7:09 p.m.