% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/addition.R
\name{time_add}
\alias{time_add}
\alias{time_subtract}
\title{Arithmetics with periods}
\usage{
time_add(
  time,
  periods = NULL,
  year = NULL,
  month = NULL,
  week = NULL,
  day = NULL,
  hour = NULL,
  minute = NULL,
  second = NULL,
  roll_month = "preday",
  roll_dst = c("post", "pre"),
  ...
)

time_subtract(
  time,
  periods = NULL,
  year = NULL,
  month = NULL,
  week = NULL,
  day = NULL,
  hour = NULL,
  minute = NULL,
  second = NULL,
  roll_month = "preday",
  roll_dst = c("pre", "post"),
  ...
)
}
\arguments{
\item{time}{date-time object}

\item{periods}{a named list of the form \code{list(year = 1, month = 2, ...)}.}

\item{year, month, week, day, hour, minute, second}{Units to be added to \code{time}. Units
except for seconds are converted to integer values. Components are replicated
according to \code{vctrs} semantics, i.e vectors must be either of length 1 or same
length as \code{time} vector.}

\item{roll_month}{controls how addition of months and years behaves when standard
arithmetic rules exceed limits of the resulting date's month. Possible values are
"preday", "boundary", "postday", "full" and "NA". See "Details" or
\verb{[(timechange::time_add())} for further details.}

\item{roll_dst}{is a string vector of length one or two. When two values are
supplied they specify how to roll date-times when they fall into "skipped" and
"repeated" DST transitions respectively. A single value is replicated to the
length of two. Possible values are:

\if{html}{\out{<div class="sourceCode">}}\preformatted{* `pre` - Use the time before the transition boundary.
* `boundary` - Use the time exactly at the boundary transition.
* `post` - Use the time after the boundary transition.
* `xfirst` - crossed-first: First time which occurred when crossing the
   boundary. For addition with positive units pre interval is crossed first and
   post interval last. With negative units post interval is crossed first, pre -
   last. For subtraction the logic is reversed.
* `xlast` - crossed-last.
* `NA` - Produce NAs when the resulting time falls inside the problematic interval.
}\if{html}{\out{</div>}}

For example `roll_dst = c("NA", "pre") indicates that for skipped intervals
return NA and for repeated times return the earlier time.

When multiple units are supplied the meaning of "negative period" is determined by
the largest unit. For example \code{time_add(t, days = -1, hours = 2, roll_dst = "xfirst")} would operate as if with negative period, thus crossing the boundary
from the "post" to "pre" side and "xfirst" and hence resolving to "post"
time. As this might result in confusing behavior. See examples.

"xfirst" and "xlast" make sense for addition and subtraction only. An error is
raised if an attempt is made to use them with other functions.}

\item{...}{deprecated}
}
\description{
Add periods to date-time objects. Periods track the change in the
"clock time" between two civil times. They are measured in common civil time
units: years, months, days, hours, minutes, and seconds.
}
\details{
Arithmetic operations with multiple period units (years, months etc) are
applied in decreasing size order, from year to second. Thus \code{time_add(x, month = 1, days = 3)} first adds 1 month to \code{x}, then ads to the resulting date 3 days.

Generally period arithmetic is undefined due to the irregular nature of
civil time and complexities with DST transitions. \pkg{`timechange`} allows
for a refined control of what happens when an addition of irregular periods
(years, months, days) results in "unclear" date.

Let's start with an example. What happens when you add "1 month 3 days" to
"2000-01-31 01:02:03"? \pkg{`timechange`} operates by applying larger
periods first. First months are added\code{1 + 1 = February} which results in
non-existent time of \verb{2000-02-31 01:02:03}. Here the \code{roll_month} adjustment
kicks in. After the adjustment, the remaining 3 days are added.

\code{roll_month} can be one of the following:
\itemize{
\item \code{boundary} - if rolling over a month boundary occurred due to setting units
smaller than month, the date is adjusted to the beginning of the month (the
boundary). For example, \verb{2000-01-31 01:02:03 + 1 month = 2000-03-01 00:00:00}.
\item \code{preday} - roll back to the last valid day of the previous month (pre-boundary
day) preserving the H, M, S units. For example, \verb{2000-01-31 01:02:03 + 1 month = 2000-02-28 01:02:03}. This is the default.
\item \code{postday} - roll to the first day post-boundary preserving the H, M, S units. For
example, \verb{2000-01-31 01:02:03 + 1 month = 2000-03-01 01:02:03}.
\item \code{full} - full rolling. No adjustment is done to the simple arithmetic operations
(the gap is skipped as if it's not there). For example, \verb{2000-01-31 01:02:03 + 1 month + 3 days} is equivalent to \verb{2000-01-01 01:02:03 + 1 month + 31 days + 3 days}
resulting in \verb{2000-03-05 01:02:03}.
\item \code{NA} - if end result was rolled over the month boundary due to addition of units
smaller than month (day, hour, minute, second) produce NA.
\item \code{NAym} - if intermediate date resulting from first adding years and months ends in
a non-existing date (e.g. Feb 31) produce NA. This is how period addition in
lubridate works for historical reasons.
}
}
\examples{

# Addition

## Month gap
x <- as.POSIXct("2000-01-31 01:02:03", tz = "America/Chicago")
time_add(x, month = 1, roll_month = "postday")
time_add(x, month = 1, roll_month = "preday")
time_add(x, month = 1, roll_month = "boundary")
time_add(x, month = 1, roll_month = "full")
time_add(x, month = 1, roll_month = "NA")
time_add(x, month = 1, day = 3,  roll_month = "postday")
time_add(x, month = 1, day = 3,  roll_month = "preday")
time_add(x, month = 1, day = 3,  roll_month = "boundary")
time_add(x, month = 1, day = 3,  roll_month = "full")
time_add(x, month = 1, day = 3,  roll_month = "NA")

## DST gap
x <- as.POSIXlt("2010-03-14 01:02:03", tz = "America/Chicago")
time_add(x, hour = 1, minute = 50, roll_dst = "pre")
time_add(x, hour = 1, minute = 50, roll_dst = "boundary")
time_add(x, hour = 1, minute = 50, roll_dst = "post")
##' time_add(x, hours = 1, minutes = 50, roll_dst = "NA")

## DST repeated time with cross-first and cross-last
(tt <- as.POSIXct(c("2014-11-02 00:15:00", "2014-11-02 02:15:00"), tz = "America/New_York"))
time_add(tt, hours = c(1, -1), roll_dst = "pre")
time_add(tt, hours = c(1, -1), roll_dst = "post")
time_add(tt, hours = c(1, -1), roll_dst = "xfirst")
time_add(tt, hours = c(1, -1), roll_dst = "xlast")

## DST skip with cross-first and cross-last
cst <- as.POSIXlt("2010-03-14 01:02:03", tz = "America/Chicago")
cdt <- as.POSIXlt("2010-03-14 03:02:03", tz = "America/Chicago")
time_add(cst, hour = 1, roll_dst = "xfirst")
time_add(cst, hour = 1, roll_dst = "xlast")
time_add(cdt, hour = -1, roll_dst = "xfirst")
time_add(cdt, hour = -1, roll_dst = "xlast")

# WARNING:
# In the following example the overall period is treated as a negative period
# because the largest unit (hour) is negative. Thus `xfirst` roll_dst results in the
# "post" time. To avoid such confusing behavior either avoid supplying multiple
# units with heterogeneous sign.
time_add(cst, hour = -1, minute = 170, roll_dst = "xfirst")

# SUBTRACTION

## Month gap
x <- as.POSIXct("2000-03-31 01:02:03", tz = "America/Chicago")
time_subtract(x, month = 1, roll_month = "postday")
time_subtract(x, month = 1, roll_month = "preday")
time_subtract(x, month = 1, roll_month = "boundary")
time_subtract(x, month = 1, roll_month = "full")
time_subtract(x, month = 1, roll_month = "NA")
time_subtract(x, month = 1, day = 0, roll_month = "postday")
time_subtract(x, month = 1, day = 3, roll_month = "postday")
time_subtract(x, month = 1, day = 0, roll_month = "preday")
time_subtract(x, month = 1, day = 3, roll_month = "preday")
time_subtract(x, month = 1, day = 3, roll_month = "boundary")
time_subtract(x, month = 1, day = 3, roll_month = "full")
time_subtract(x, month = 1, day = 3, roll_month = "NA")

## DST gap
y <- as.POSIXlt("2010-03-15 01:02:03", tz = "America/Chicago")
time_subtract(y, hour = 22, minute = 50, roll_dst = "pre")
time_subtract(y, hour = 22, minute = 50, roll_dst = "boundary")
time_subtract(y, hour = 22, minute = 50, roll_dst = "post")
time_subtract(y, hour = 22, minute = 50, roll_dst = "NA")


}
