Shifts time points by a duration, like x + by, with control over how time
points that don't exist in the target granule are resolved. Shifting by a
duration with an irregular relationship to the time points' chronon (e.g.
days within months) can produce time points that don't exist, such as
shifting 31 January by one month. In a time zone, shifting by days or
longer keeps the local clock time, which may have been skipped when daylight
saving starts (e.g. 02:30 on the day clocks go forward from 02:00 to 03:00).
The + and - operators use the default strategy, set by the
mixtime.on_invalid option ("clamp" unless set).
Usage
time_shift(x, by, on_invalid = getOption("mixtime.on_invalid", "clamp"))Arguments
- x
A time point vector.
- by
A time
duration()(e.g.,months(1L)), or a character string specifying one (e.g.,"1 month").- on_invalid
How to resolve time points that don't exist in the target granule. Defaults to the
mixtime.on_invalidoption, or"clamp"if it isn't set:"clamp": Reduce the invalid component to its last valid value, preserving finer components (e.g., the time of day). A skipped local time moves back by the size of the gap (02:30 becomes 01:30)."previous": Use the last valid time point before the invalid one, the end of the target granule, so finer components are not preserved. For discrete time this is the last chronon within the granule (e.g., 23:59:59 on the last day); for continuous time it is the end of that chronon, the same instant as"next". A skipped local time becomes the end of the valid time before the gap (01:59:59)."next": Use the first valid time point after the invalid one, the start of the following granule, so finer components are not preserved (e.g., 00:00:00 on the first day of the following month). A skipped local time becomes the start of the valid time after the gap (03:00)."overflow": Allow the invalid component to overflow into the next granule. A skipped local time moves forward by the size of the gap (02:30 becomes 03:30)."reject": ReturnNAwith a warning."error": Throw an error.
"previous"and"next"preserve the order of the time points being shifted, although distinct time points may become equal."clamp"and"overflow"do not: shifting1955-01-29 23:00:00and1955-01-31 08:00:00by one month clamps them to1955-02-28 23:00:00and1955-02-28 08:00:00, reversing their order.
Examples
x <- datetime("2021-01-30 09:30:00")
time_shift(x, months(1L))
#> <mixtime[1]>
#> [1] 2021-02-28 09:30:00
time_shift(x, months(1L), on_invalid = "previous")
#> <mixtime[1]>
#> [1] 2021-02-28 23:59:59
time_shift(x, months(1L), on_invalid = "next")
#> <mixtime[1]>
#> [1] 2021-03-01 00:00:00
time_shift(x, months(1L), on_invalid = "overflow")
#> <mixtime[1]>
#> [1] 2021-03-02 09:30:00
time_shift(x, months(1L), on_invalid = "reject")
#> Warning: 1 time point did not exist in the target granule and was replaced with "NA".
#> ℹ Set `on_invalid` to "clamp", "previous", "next", or "overflow" to resolve
#> them to valid time points instead.
#> <mixtime[1]>
#> [1] NA
try(time_shift(x, months(1L), on_invalid = "error"))
#> Error : 1 time point did not exist in the target granule, at position 1.
#> ℹ Set `on_invalid` to "clamp", "previous", "next", or "overflow" to resolve
#> them to valid time points instead.
# Shifting backwards
time_shift(date("2021-03-31"), months(-1L), on_invalid = "overflow")
#> <mixtime[1]>
#> [1] 2021-03-03
# 02:30 doesn't exist on 2025-10-05 in Melbourne (clocks go forward at 02:00)
x <- datetime(as.POSIXct("2025-10-04 02:30", tz = "Australia/Melbourne"))
time_shift(x, days(1L))
#> <mixtime[1]>
#> [1] 2025-10-05 01:30:00 AEST
time_shift(x, days(1L), on_invalid = "previous")
#> <mixtime[1]>
#> [1] 2025-10-05 01:59:59 AEST
time_shift(x, days(1L), on_invalid = "next")
#> <mixtime[1]>
#> [1] 2025-10-05 03:00:00 AEDT
time_shift(x, days(1L), on_invalid = "overflow")
#> <mixtime[1]>
#> [1] 2025-10-05 03:30:00 AEDT