| Title: | A Common Representation of Time Indices of Different Types |
| Version: | 0.2 |
| Date: | 2025-10-18 |
| Description: | Provides an easy-to-use tind class representing time indices of different types (years, quarters, months, ISO 8601 weeks, dates, time of day, date-time, and arbitrary integer/numeric indices). Includes an extensive collection of functions for calendrical computations (including business applications), index conversions, index parsing, and other operations. Auxiliary classes representing time differences and time intervals (with set operations and index matching functionality) are also provided. All routines have been optimised for speed in order to facilitate computations on large datasets. More details regarding calendars in general and calendrical algorithms can be found in "Calendar FAQ" by Claus Tøndering https://www.tondering.dk/claus/calendar.html. |
| Depends: | R (≥ 3.6.0) |
| Suggests: | crayon, methods, stats, testthat, knitr, rmarkdown, fansi, htmltools |
| Enhances: | utils, graphics, ggplot2, zoo, timeDate, chron, data.table |
| Collate: | base-utils.R base-in.R base-yqmwd.R base-tz.R base-th.R base-res.R base-pretty.R base-locale.R base-types.R base-parse.R tind.R format.R parse.R coercion.R methods.R tdiff.R tinterval.R types.R resolution.R tzone.R tspan.R print_summ_str.R ops.R setops_match.R round.R cut.R seq.R ord_reg.R calendar.R other.R calendars.R business.R merge.R pretty.R plot-scales.R package.R |
| License: | GPL-3 |
| URL: | https://github.com/dever-pl/tind |
| BugReports: | https://github.com/dever-pl/tind/issues |
| Encoding: | UTF-8 |
| NeedsCompilation: | yes |
| VignetteBuilder: | knitr |
| RoxygenNote: | 7.3.3 |
| Packaged: | 2025-10-18 19:06:55 UTC; dever |
| Author: | Grzegorz Klima [aut, cre, cph] |
| Maintainer: | Grzegorz Klima <dever@post.pl> |
| Repository: | CRAN |
| Date/Publication: | 2025-10-22 19:10:02 UTC |
A Common Representation of Time Indices of Different Types
Description
The goal of tind project is to provide users with a single class capable of representing time indices of different types. Currently, these include: years, quarters, months, ISO 8601 weeks, dates, time of day, date-time, and arbitrary integer/numeric indices. tind provides a unified interface and a collection of methods, which can be used with all supported index types.
The package provides an extensive collection of functions for calendrical computations (including business applications), index conversions, index parsing, and other operations. Examples of use of tind functions and methods can be found in their documentation and in package vignettes.
All routines have been optimised for speed in order to facilitate computations on large datasets.
Details
Options Controlling tind Behaviour
tind.abbr.year.start is a number in range 0–99 determining how
two-digit years are interpreted during parsing. By default (69), two-digit
numbers smaller than 69 are interpreted as years in 2000s and equal or greater
than 69 as years in 1900s.
tind.warn.diff.tz is a logical value (TRUE by default)
determining whether warnings should be raised when performing computations
involving date-time indices with different time zone attributes.
Implementation
The code structure is hierarchical by design. The first layer consists of low-level C and R functions working with particular time index types and converting between them. The second layer consists of exported (user-accessible) functions, which are responsible for argument checks and dispatching to the 1st layer functions.
Computations with tind for types other than date-time are
implemented in C from scratch. Many algorithms were taken
from Calendar FAQ by Claus Tøndering. For date-time computations,
tind partially relies on base R infrastructure (POSIXlt
class), that is on conversion as.POSIXlt.numeric.
Author(s)
Grzegorz Klima <dever@post.pl>
References
Claus Tøndering, Calendar FAQ, https://www.tondering.dk/claus/calendar.html.
Operations Involving Time Indices, Time Differences, and Time Intervals
Description
Basic arithmetic and comparison operators are implemented for time indices, time differences, and time intervals where applicable.
Operators + and - allow for shifting
time indices and computing differences between two indices. Time intervals
can be shifted using these, too. When the second operand in + and -
is numeric the underlying time unit is used. For time of day and date-time indices
this is always a second.
Convenience operators
%+y%, %-y%, %+q%, %-q%,
%+m%, %-m%, %+w%, %-w%,
%+d%, %-d%, %+h%, %-h%,
%+min%, %-min%, %+s%, and %-s%
can used to shift time indices (and intervals) by years, quarters, months,
weeks, days, hours minutes, and seconds.
See Details for their behaviour in corner cases.
For all index types except for integer and numeric indices differences
between time indices are retuned as objects of tdiff class.
Comparison operators are available for time indices (tind)
and time differences (tdiff).
Usage
## S3 method for class 'tind'
Ops(e1, e2)
e1 %+y% e2
e1 %-y% e2
e1 %+q% e2
e1 %-q% e2
e1 %+m% e2
e1 %-m% e2
e1 %+w% e2
e1 %-w% e2
e1 %+d% e2
e1 %-d% e2
e1 %+h% e2
e1 %-h% e2
e1 %+min% e2
e1 %-min% e2
e1 %+s% e2
e1 %-s% e2
Arguments
e1, e2 |
a |
Details
One can only subtract from time indices and divide time differences.
Unary + and - operators are supported for tdiff only.
Results of arithmetic operations are always validated and can become NAs
(when out of range) or be rounded, for example, when dividing
time differences in days by numbers that are not divisors.
Shifting time intervals beyond valid index ranges can lead to spurious results
as beginnings or ends of time intervals become NAs and intervals can become
entire line.
== and != operators for time indices only accept same types
of indices. The remaining comparison operators accept different types
provided that conversion can be performed.
Corner Cases
When shifting dates by months one is faced with a dilemma:
should month after March 31st be April 30th or May 1st?
The convention in tind is that the result of %+m% n
always falls in the nth month after the month in which
a given date falls and in corner cases the last day in the resulting
month is returned. Similar logic is applied to shifts by years
and quarters as well as shifts of weeks by years (some years have 53 weeks).
See Examples.
Shifting date-time indices by days can also be problematic in front of DST changes,
when the resulting date has 23 hours (one hour missing) or 25 hours
(one hour repeated). When hour is missing, the next hour is selected (no NA
is returned). When hour is doubled, the second occurrence
is selected. See Examples.
Value
Comparison operators and ! return logical vectors.
Differences of time indices are returned as objects of tdiff class,
except for arguments of type "i" or "n" (integer/numeric
indices), in which case an integer or numeric vector is returned.
Shifting time indices and time intervals produces time indices and time intervals, respectively.
Operations involving time differences return time differences.
See Also
tind class and its constructor,
calendrical-computations for calendrical computations.
Examples
# list the last 10 days including today
today() + (-9:0)
# how many days have passed since the beginning of the year?
today() - floor_t(today(), "y")
# same but the result is not tdiff
day_of_year(today()) - 1
# single time interval
x <- "2024-06-01 08:00" %--% "2024-06-01 16:00"
# shift by 0, 1, ..., 5 days
x %+d% 0:5
# are we in or after 2026?
today() >= 2026
# are we after 2025?
today() > 2025
# corner cases - ends of months and shifts by months
as.date("2024-01-31") %+m% 0:5
# same
as.date("2024-01-31") + mnths(0:5)
# corner cases - 53rd week of year
as.week(202053) %-y% 0:5
# corner cases - DST changes and shifts by days
if ("Europe/Warsaw" %in% OlsonNames()) {
# 2020-10-25 had 25h with 02:00 repeated
print(as.date_time("2020-10-24 02:00", tz = "Europe/Warsaw") %+h% 23:26)
print(as.date_time("2020-10-24 02:00", tz = "Europe/Warsaw") %+d% 1)
print(as.date_time("2020-10-26 02:00", tz = "Europe/Warsaw") %-h% 26:23)
print(as.date_time("2020-10-26 02:00", tz = "Europe/Warsaw") %-d% 1)
# 2021-03-28 had 23h with 02:00 missing
print(as.date_time("2021-03-27 02:00", tz = "Europe/Warsaw") %+h% 22:25)
print(as.date_time("2021-03-27 02:00", tz = "Europe/Warsaw") %+d% 1)
print(as.date_time("2021-03-29 02:00", tz = "Europe/Warsaw") %-h% 25:22)
print(as.date_time("2021-03-29 02:00", tz = "Europe/Warsaw") %-d% 1)
}
Conversion to tind Class
Description
as.tind method allows for conversion of numeric and character vectors
as well as objects of Date, POSIXct, and POSIXlt
classes to tind objects to tind.
as.tind method for tind class allows to change the type
of index of an object of tind class.
Convenience functions as.year, as.quarter, as.month,
as.week, as.date, as.date_time, as.time allow
to quickly convert argument to the indicated type.
Usage
as.tind(x, ...)
## S3 method for class 'numeric'
as.tind(x, type = NULL, tz = NULL, ...)
## S3 method for class 'character'
as.tind(
x,
type = NULL,
format = NULL,
order = NULL,
locale = NULL,
tz = NULL,
...
)
## S3 method for class 'Date'
as.tind(x, ...)
## S3 method for class 'POSIXct'
as.tind(x, tz = NULL, digits = 0L, ...)
## S3 method for class 'POSIXlt'
as.tind(x, tz = NULL, digits = 0L, ...)
## S3 method for class 'data.frame'
as.tind(x, ...)
## S3 method for class 'tind'
as.tind(x, type = NULL, tz = NULL, ...)
as.year(x, ...)
as.quarter(x, ...)
as.month(x, ...)
as.week(x, ...)
as.date(x, ...)
as.date_time(x, tz = NULL, ...)
as.time(x, ...)
Arguments
x |
an R object (e.g., a numeric vector, a character vector, a |
... |
further arguments passed to or from other methods. |
type |
a character determining time index type or |
tz |
(optional) a character value determining the time zone (the default
|
format |
a character determining input format(s) as in |
order |
a character determining order(s) of time index components
in the input as in |
locale |
(optional) a character value determining locale or |
digits |
an integer value (0–6) determining the number of decimal places for seconds to be preserved during conversion (0 by default). |
Details
Numeric vectors
The following numeric representations are automatically recognised
(between year 1800 and 2199): YYYY (years), YYYYQ (quarters),
YYYYMM (months), and YYYYMMDD (dates). Conversion from
numeric vectors to other index types requires type specification via type
argument.
Date-time indices are represented as number of seconds since the Epoch (1970-01-01 00:00 UTC). Time of day is represented as the number of seconds since midnight.
Character vectors
as.tind automatically recognises many different formats. If automatic
recognition fails, type argument could help identify the format.
For less standard formats / representations, one can use either format
argument (which is forwarded to strptind) or order
argument (which is forwarded to parse_t).
Data frames
If a data frame has one column, it is converted using appropriate method
depending on the column type. In case there are two or more columns, they are
pasted and the resulting character vector is parsed. As this may not be
computationally efficient, other ways of constructing tind should be
considered, for example, use of tind constructor.
Date and POSIXt classes
Conversion of Date objects returns time index of type "d" (date).
POSIXct and POSIXlt classes are converted to index of type "t"
(date-time). If time zone attribute is not set for the argument, system time zone
is assumed.
Other classes representing time indices
For conversions between tind class and other classes (from packages
other than base), see tind-other.
Value
An object of tind class of length equal to the length of the argument.
For data frame version the length of the result is equal to the number of rows
in the data frame.
See Also
tind constructor,
strptind function for format specifications,
parse_t function for order specifications,
tind-coercion for conversions from tind,
and tind-other for conversions between tind class and
other classes (from packages other than base).
Examples
## numeric and character arguments
# years
as.tind(1999)
as.tind("1999")
# quarters
as.tind(20043)
as.tind("20043")
# months
as.tind(200109)
as.tind("2001-09")
as.tind("200109")
# need proper locale to recognise English month names
as.tind("Sep 2001", locale = "C")
# weeks (ISO 8601)
# numeric YYYYWW representation is not automatically recognised, need type
as.tind(200936, "w")
as.tind("2009-W36")
# dates
as.tind(20200726)
as.tind("2020-07-26")
# need proper locale to recognise English month names
as.tind("Jul 26, 2020", locale = "C")
as.tind("07/26/20")
# date-time
as.tind("2000-08-16 08:17:38")
# time
as.tind("08:17:38")
as.tind(08 * 3600 + 17 * 60 + 38, type = "h")
## conversion from Date and POSIXct
as.tind(Sys.Date())
as.tind(Sys.time())
## as.year, ..., as.time
# today
(x <- today())
as.year(x)
as.quarter(x)
as.month(x)
as.week(x)
# midnight
as.date_time(x)
# current time
(x <- now())
as.year(x)
as.quarter(x)
as.month(x)
as.week(x)
as.date(x)
as.time(x)
Get the Same Date and Time in a Different Time Zone
Description
This method allows to determine time index representing the same date and time in a different time zone.
Usage
as.tzone(x, tz)
## S3 method for class 'tind'
as.tzone(x, tz)
## S3 method for class 'POSIXct'
as.tzone(x, tz)
## S3 method for class 'POSIXlt'
as.tzone(x, tz)
## S3 method for class 'tinterval'
as.tzone(x, tz)
Arguments
x |
an object of |
tz |
a character value determining the new time zone.
See |
Details
The underlying time (as measured by number of seconds since the Unix epoch in UTC)
will change so that the date-time components in the new and old time zones
are the same. For tind arguments, if (due to DST time changes or UTC
offset changes) date-time indices do not occur in the new time zone,
NAs are introduced with a warning. For tinterval arguments, the result
is adjusted with a warning, in order not to create open-ended time intervals.
The method is implemented for objects of tind class of type "t"
(date-time), objects of tinterval class of type "t" (time intervals),
as well as base POSIXct and POSIXlt classes.
List of time zones supported by the particular R installation can be obtained
via a call to OlsonNames function.
Value
An object of the same class and length as x with adjusted
underlying date-time representation and time zone set to tz.
See Also
tzone method and date_time for construction
od date-time indices from its components.
Examples
if (all(c("Europe/Warsaw", "America/New_York") %in% OlsonNames())) {
# check time in one time zone
print(nw <- now(tz = "Europe/Warsaw"))
# the same date-time in a new time zone
print(nw2 <- as.tzone(nw, "America/New_York"))
# note the time difference (equal to the difference of UTC offsets)
# warning on different time zones will be issued
print(suppressWarnings(nw2 - nw))
try(nw2 - nw)
}
Add Time Axis — Plotting with graphics Package
Description
axis.tind adds time axis to a plot. Axes will be added automatically
by graphics, but the default behaviour can be overridden by plotting
without axis and then calling axis.tind, see Examples.
Usage
axis.tind(
side,
x,
at,
format = NULL,
locale = NULL,
labels = TRUE,
n.breaks = 5L,
...
)
Arguments
side |
see |
x |
time indices for which an axis is to be created. |
at |
(optional) time indices at which manual tick-marks and labels should be placed. |
format |
(optional) a character string determining label format
or a formatting function, see |
locale |
(optional) a character string determining locale to be used for formatting labels, see calendar-names for information on locale settings. |
labels |
a logical value determining whether automatic labels should be placed at tick-marks or a character vector of labels. |
n.breaks |
an integer value, desired number of breaks. |
... |
further arguments passed to |
Value
Same as for axis, used for its side effect,
which is to add time axis to an existing plot.
See Also
pretty for computing pretty breakpoints,
axis_t for calculating axis parameters,
scale_tind for creating axes with ggplot2.
Examples
# load graphics
library(graphics)
# artificial data
N <- 100
df <- data.frame(d = today() + (-N + 1):0, y = cumsum(rnorm(N)))
# default axis
plot(df$d, df$y, type = "l")
# custom date format with potentially more breaks and a smaller font
plot(df$d, df$y, type = "l", xaxt = "n")
axis.tind(1, df$d, format = "%m/%d/%y", n.breaks = 7L, cex.axis = .9)
Compute Time Axis Parameters for Plotting
Description
Auxiliary function axis_t returns a six-element list with axis
limits (in Cartesian coordinates), tick-mark positions (in Cartesian
coordinates), tick-mark labels (character vector), positioning of minor
tick-marks (in Cartesian coordinates), resolution of indices (in Cartesian
coordinates), and limits argument converted to a tinterval
of the same index type as x. The results can be used for manual creation
of axes in plots.
Usage
axis_t(
x,
limits = NULL,
format = NULL,
locale = NULL,
expand = FALSE,
n.breaks = 5L
)
Arguments
x |
time indices for which an axis is to be created. |
limits |
|
format |
(optional) a character string determining label format
(see |
locale |
(optional) a character string determining locale to be used for formatting labels, see calendar-names for information on locale settings. |
expand |
a logical value. If |
n.breaks |
an integer value, desired number of breaks. |
Value
A six-element list with scale limits (lim), vector of tick-mark
positions (at), character vector with tick-mark labels (labels),
vector of minor tick-mark positions (minor), resolution (in Cartesian
coordinates) of time indices (resolution), and limits argument
converted to a tinterval of the same index type as x (limits).
See Also
pretty for computing pretty breakpoints,
axis.tind for creating axes with graphics package,
scale_tind for creating axes with ggplot2.
Examples
# load graphics
library(graphics)
# artificial data
N <- 180
df <- data.frame(d = today() + (-N + 1):0, y = cumsum(rnorm(N)))
(axt <- axis_t(df$d, format = "%m/%d/%y", n.breaks = 6L))
# custom time axis with minor breaks
plot(df$d, df$y, xlim = axt$lim, type = "l", xaxt = "n", xaxs = "i")
axis(1, at = axt$lim, labels = FALSE, lwd = 1, lwd.ticks = 0)
axis(1, at = axt$at, labels = axt$labels, lwd = 0, lwd.ticks = .7)
axis(1, at = axt$minor, labels = FALSE, lwd = 0, lwd.ticks = .4)
Business Days
Description
bizday computes the nearest business day from the date given
a calendar function and one of the date rolling conventions (see Details).
bizday_advance advances date(s) by n business days.
next_bizdays determines the following n business days after a date.
first_bizday_in_month/quarter and last_bizday_in_month/quarter
determine the first and the last business day in a month and a quarter.
bizdays_in_month, bizdays_in_quarter, and bizdays_in_year
return the number of business days in particular time period.
bizday_diff computes the number of business days between two dates.
Usage
bizday(d, convention, calendar)
bizday_advance(d, n = 1L, calendar)
next_bizdays(d, n = 1L, calendar)
first_bizday_in_month(m, calendar)
last_bizday_in_month(m, calendar)
first_bizday_in_quarter(q, calendar)
last_bizday_in_quarter(q, calendar)
bizdays_in_month(m, calendar)
bizdays_in_quarter(q, calendar)
bizdays_in_year(y, calendar)
bizday_diff(d1, d2, calendar, start.incl = TRUE, end.incl = FALSE)
Arguments
d |
an object of |
convention |
a character value determining date rolling convention, see Details. |
calendar |
a function determining working days and holidays (see Details)
or |
n |
an integer vector (for |
m |
an object of |
q |
an object of |
y |
an object of |
d1 |
an object of |
d2 |
an object of |
start.incl |
a logical value, if |
end.incl |
a logical value, if |
Details
The vectorised implementations of bizday, bizday_advance,
and next_bizdays work under the assumption of at least one business day
in a week and could return NAs for pathological calendar functions.
bizday_advance with increment 0 will adjust the date to the first
preceding business day if it is not a business day (will act as
bizday(d, "p", *)).
next_bizdays accepts negative arguments and returns an increasing
sequence of business dates prior to d of length abs(n).
Conventions
The following date rolling conventions are supported (applied when the day is not a business day):
"p"preceding, the previous business day,
"f"following, the next business day,
"mp"modified preceding, the previous business day unless it falls in the previous month, in which case the next business day is chosen,
"mf"modified following, the next business day unless it falls in the next month, in which case the the previous business day is chosen,
"mf2"modified following bimonthly, the next business day unless it falls in the next month or the next half of the month (after 15th), in which case the the previous business day is chosen.
Calendar Functions
Calendar function should take a vector of days as an argument and return
a logical vector of the same length marking business days (as TRUE)
or a list of two or three logical vectors of the same length with the first
marking business days. See also calendars for real-life
examples of calendar functions. When calendar function is not supplied,
Monday-Friday are marked as business days.
Value
bizday and first/last_bizday_in_month/quarter return
vectors of dates of the same length as their first argument.
bizday_advance returns a vector of dates of length equal to length
of the longer of the first two arguments (d and n).
next_bizdays returns a vector of dates of length abs(n).
bizday_diff and bizdays_in_month/quarter/year return integer
vectors.
See Also
calendars for examples of calendar functions,
daycount_frac for computations of day count fractions /
accrual factors.
Examples
# a trivial calendar function (Mon-Fri)
monfri <- function(d) (day_of_week(d) <= 5L)
# 2022-10-01 was Saturday
calendar("2022-10", monfri)
(d <- as.date("2022-10-01"))
bizday(d, "p", monfri)
bizday(d, "mp", monfri)
bizday(d, "f", monfri)
bizday(d, "mf", monfri)
bizday(d, "mf2", monfri)
# 2022-10-15 was Saturday again
calendar("2022-10", monfri)
(d <- as.date("2022-10-15"))
bizday(d, "p", monfri)
bizday(d, "mp", monfri)
bizday(d, "f", monfri)
bizday(d, "mf", monfri)
bizday(d, "mf2", monfri)
# 2022-12-31 was also Saturday
calendar("2022-12", monfri)
(d <- as.date("2022-12-31"))
bizday(d, "p", monfri)
bizday(d, "mp", monfri)
bizday(d, "f", monfri)
bizday(d, "mf", monfri)
bizday(d, "mf2", monfri)
Calendar Names
Description
These three functions return (abbreviated and full) names of months and days of week as well as AM/PM indicators in the current or user-provided locale.
How the month and weekday names are actually returned depends both on the selected locale and character set / code page setting.
Usage
month_names(locale = NULL, abbreviate = TRUE)
weekday_names(locale = NULL, abbreviate = TRUE)
ampm_indicators(locale = NULL)
Arguments
locale |
a character value determining locale or |
abbreviate |
a logical value, if |
Value
A character vector of length 12, 7, or 2.
Locale Settings
Unfortunately, locale and character set naming were not standardised across
different operating systems for many years. On modern operating systems,
however, locale is usually of the form xx_XX (xx for language,
XX for country) optionally followed by a dot and a character set
identifier, for example, UTF-8.
"C" is a special locale that should always be available and
defaults to American English.
See Also
format for formatting objects of tind class.
Examples
# current system locale
month_names()
weekday_names()
try(
ampm_indicators()
)
try({
# English abbreviated month names
print(month_names("en_GB"))
# French month names
print(month_names("fr_FR.UTF-8", FALSE))
# German abbreviated month names
print(month_names("de_DE.UTF-8"))
# Polish abbreviated month names
print(month_names("pl_PL.UTF-8"))
# English weekday names
print(weekday_names("en_GB", FALSE))
# French abbreviated weekday names
print(weekday_names("fr_FR.UTF-8"))
# German weekday names
print(weekday_names("de_DE.UTF-8", FALSE))
# Polish abbreviated weekday names
print(weekday_names("pl_PL.UTF-8"))
# US am/pm indicators
print(ampm_indicators("en_US"))
# UK am/pm indicators
print(ampm_indicators("en_GB"))
})
Working with Custom Calendars
Description
tind package provides an extensive collection of functions for
calendrical computations allowing users to write custom calendar functions
that can be used to mark business days, holidays, and other observances.
See Writing custom calendar functions for an introduction to such
functions and Examples for two real-life examples. These functions can
later be used for pretty printing calendars on the console (using
calendar function), quick identification of business days, holidays,
and other observances (using eval_calendar function) and business day
computations (see bizday).
calendar pretty prints a calendar for year(s) or month(s)
on the console using user-provided calendar function determining business
days and holidays.
eval_calendar applies user-provided calendar function to a sequence
of dates. It is designed to be used by developers who wish to implement
new applications of custom calendars.
Usage
calendar(ym, calendar = NULL, name = NULL, locale = NULL)
eval_calendar(d, calendar)
Arguments
ym |
an object of |
calendar |
a function determining working days and holidays (see Details),
or |
name |
(optional) a character value (a short string) to be printed beside
the year or month (or |
locale |
(optional) a character value determining locale or |
d |
an object of |
Details
calendar uses crayon package (when available) for highlighting
dates. When calendar function (calendar argument) is not provided,
Monday-Friday are marked as working days. Current date is marked by square
brackets ([]).
For months, calendar additionally prints information about observances
in a month provided that values in the list returned by the function
passed as calendar argument are named.
Value
calendar returns invisible NULL and is used for its side effects.
eval_calendar returns a 3-element list of tind objects representing
business days ($bizdays), holidays ($holidays), and other
observances ($otherobs).
Writing Custom Calendar Functions
Calendar function should take a vector of dates as an argument and return
logical vector of the same length marking business days (as TRUE)
or a list of two or three logical vectors of the same length with the first
marking business days (as TRUE), the second marking holidays (as TRUE),
and the third marking other observances / events (as TRUE).
The second and the third returned logical vectors can be named indicating
which observances are marked.
The 4 basic functions to be used when writing calendars are: year,
month, day, and day_of_week.
These can be used to mark fixed observances and weekends.
nth_dw_in_month and last_dw_in_month can be used
to determine dates of movable observances falling on the nth or the last occurrence
of a day of week in a particular month.
easter function can be used to determine date of Easter in
a year as well as of other movable observances with a fixed distance from
Easter.
Two examples of calendar functions are provided below. These two functions can be used as templates for developing custom calendar functions. In the examples, one will also find a programming trick to easily name holidays and other observances.
A Note on the Design
One could argue that a design in which calendar functions should return
logical vectors or lists of logical vectors is not intuitive and tind
(vectors of dates) should be returned instead (thus making eval_calendar
function redundant). Firstly, logical vectors are easy and fast to work with.
By definition, a business day or a holiday must satisfy some conditions,
which leads to logical values. Secondly, in some applications (for example
counting business days) one would have to use matching to get integers
or logical values back from time indices.
Note
tind package does not provide a calendar for any country, region, or market. Instead, it gives users all the tools necessary to create customised calendars. See Examples section below for real-life examples of calendar functions, which could be used as templates.
See Also
time-index-components, calendrical-computations,
Ops, bizday.
Examples
# US (federal) calendar with holiday names
calendar_US <- function(dd)
{
dd <- as.tind(dd)
y <- year(dd)
m <- month(dd)
d <- day(dd)
newyear <- (m == 1) & (d == 1)
martinlking <- (y >= 2000) & (m == 1) & (dd == nth_dw_in_month(3, 1, dd))
presidentsday <- (m == 2) & (dd == nth_dw_in_month(3, 1, dd))
memorialday <- (m == 5) & (dd == last_dw_in_month(1, dd))
juneteenth <- (y >= 2021) & (m == 6) & (d == 19)
independence <- (m == 7) & (d == 4)
labor <- (m == 9) & (dd == nth_dw_in_month(1, 1, dd))
columbus <- (m == 10) & (dd == nth_dw_in_month(2, 1, dd))
veterans <- (m == 11) & (d == 11)
thanksgiving <- (m == 11) & (dd == nth_dw_in_month(4, 4, dd))
christmas <- (m == 12) & (d == 25)
holiday <- newyear | martinlking | presidentsday |
memorialday | juneteenth | independence |
labor | columbus | veterans | thanksgiving |
christmas
# holiday names - a programming trick
# names of holnms should be the same as names of logical vectors above
names(holiday) <- rep("", length(holiday))
holnms <- c(newyear = "New Year's Day",
martinlking = "Birthday of Martin Luther King, Jr.",
presidentsday = "Washington's Birthday",
memorialday = "Memorial Day",
juneteenth = "Juneteenth National Independence Day",
independence = "Independence Day",
labor = "Labor Day",
columbus = "Columbus Day",
veterans = "Veterans Day",
thanksgiving = "Thanksgiving Day",
christmas = "Christmas Day")
lapply(names(holnms), function(nm) names(holiday)[get(nm)] <<- holnms[nm])
# business days
business <- !holiday & (day_of_week(dd) %in% 1:5)
return (list(bizdays = business, holiday = holiday))
}
# Polish calendar from 1990 on with holiday names as well as other
# observances named
calendar_PL <- function(dd)
{
dd <- as.tind(dd)
y <- year(dd)
m <- month(dd)
d <- day(dd)
# public holidays
newyear <- (m == 1L) & (d == 1L)
epiphany <- (y >= 2011L) & (m == 1L) & (d == 6L)
easterd <- easter(dd) == dd
eastermon <- easter(dd) + 1L == dd
labour <- (m == 5L) & (d == 1L)
constitution <- (m == 5L) & (d == 3L)
pentecost <- easter(dd) + 49L == dd
corpuschristi <- easter(dd) + 60L == dd
assumption <- (m == 8L) & (d == 15L)
allsaints <- (m == 11L) & (d == 1L)
independence <- (m == 11L) & (d == 11L)
christmaseve <- (m == 12L) & (d == 24L) & (y >= 2025)
christmas <- (m == 12L) & (d == 25L)
christmas2 <- (m == 12L) & (d == 26L)
holiday <- newyear | epiphany |
easterd | eastermon |
labour | constitution |
pentecost | corpuschristi |
assumption |
allsaints | independence |
christmaseve | christmas | christmas2
# holiday names
names(holiday) <- rep("", length(holiday))
holnms <- c(newyear = "New Year", epiphany = "Epiphany",
easterd = "Easter", eastermon = "Easter Monday",
labour = "Labour Day", constitution = "Constitution Day",
pentecost = "Pentecost", corpuschristi = "Corpus Christi",
assumption = "Assumption of Mary",
allsaints = "All Saints Day", independence = "Independence Day",
christmaseve = "Christmas Eve",
christmas = "Christmas", christmas2 = "Christmas (2nd day)")
lapply(names(holnms), function(nm) names(holiday)[get(nm)] <<- holnms[nm])
# working/business days
work <- !holiday & (day_of_week(dd) <= 5L)
# other observances
fatthursday <- easter(dd) - 52L == dd
shrovetuesday <- easter(dd) - 47L == dd
ashwednesday <- easter(dd) - 46L == dd
goodfriday <- easter(dd) - 2L == dd
primaaprilis <- (m == 4L) & (d == 1L)
flagday <- (m == 5L) & (d == 2L)
mothersday <- (m == 5L) & (d == 26L)
childrensday <- (m == 6L) & (d == 1L)
saintjohnseve <- (m == 6L) & (d == 23L)
allsoulsday <- (m == 11L) & (d == 2L)
saintandrewseve <- (m == 11L) & (d == 29L)
saintnicholasday <- (m == 12L) & (d == 6L)
christmaseve <- (m == 12L) & (d == 24L) & (y < 2025)
newyeareve <- (m == 12L) & (d == 31L)
other <- fatthursday | shrovetuesday | ashwednesday |
goodfriday |
primaaprilis |
flagday |
mothersday | childrensday | saintjohnseve |
allsoulsday |
saintandrewseve |
saintnicholasday | christmaseve |
newyeareve
names(other) <- rep("", length(other))
othernms <- c(fatthursday = "Fat Thursday",
shrovetuesday = "Shrove Tuesday",
ashwednesday = "Ash Wednesday",
goodfriday = "Good Friday",
primaaprilis = "All Fool's Day",
flagday = "Flag Day",
mothersday = "Mother's Day",
childrensday = "Children's Day",
saintjohnseve = "Saint John's Eve",
allsoulsday = "All Souls' Day",
saintandrewseve = "Saint Andrew's Eve",
saintnicholasday = "Saint Nicholas Day",
christmaseve = "Christmas Eve",
newyeareve = "New Year's Eve")
lapply(names(othernms), function(nm) names(other)[get(nm)] <<- othernms[nm])
return (list(work = work, holiday = holiday, other = other))
}
# print the calendar for the current and the previous/next month and the current year
# (Mon-Fri marked as working days)
calendar()
calendar(as.year(today()))
# print Polish and US calendars for 2020 and the current year
calendar(2020, calendar = calendar_PL)
calendar(2020, calendar = calendar_US)
calendar(as.year(today()), calendar = calendar_PL)
calendar(as.year(today()), calendar = calendar_US)
# print Polish and US calendars for 2020-01 and the current and the previous/next month
calendar("2020-01", calendar = calendar_PL)
calendar("2020-01", calendar = calendar_US)
calendar(calendar = calendar_PL)
calendar(calendar = calendar_US)
# get list of business days, holidays for 2020-01 and the current month
# using Polish and US calendars
d202001 <- seq(as.date("2020-01-01"), "2020-01-31")
dcurrmnth <- seq(floor_t(today(), "m"), last_day_in_month(today()))
eval_calendar(d202001, calendar_PL)
eval_calendar(d202001, calendar_US)
eval_calendar(dcurrmnth, calendar_PL)
eval_calendar(dcurrmnth, calendar_US)
# print calendars with names
calendar(calendar = calendar_PL, name = "PL")
calendar(calendar = calendar_US, name = "US (federal)")
# print Polish calendar using Polish locale
try(
calendar(calendar = calendar_PL, locale = "pl_PL.UTF-8")
)
Calendrical Computations in tind Package
Description
The following functions can be used for calendrical computations, especially determining dates of movable observances. All function are vectorised.
nth_day_of_year returns the date of the nth day of a year.
last_day_in_month and last_day_in_quarter return the date
of the last day in a month or a quarter.
nth_dw_in_month returns the date of the nth day
of week in a month.
last_dw_in_month returns the date of the last day
of week in a month.
easter returns the date of Easter in a year.
Usage
nth_day_of_year(nth, y)
last_day_in_month(m)
last_day_in_quarter(q)
nth_dw_in_month(nth, dw, m)
last_dw_in_month(dw, m)
easter(y)
Arguments
nth |
a numeric value or vector of indices (1–366 for |
y, q, m |
an object of |
dw |
a numeric value or vector of days of week (values in range 1–7 with Monday as the 1st day). |
Value
An object of tind class with dates (type "d").
See Also
time-index-components, time-index-properties,
Ops. Further examples of application of these functions
can be found in calendar documentation. For calendrical
computations involving business days see bizday.
Examples
# Thanksgiving in the US is observed on the fourth Thursday of November,
# which in 2019 was on:
nth_dw_in_month(4, 4, 201911)
# and Black Friday?
nth_dw_in_month(4, 4, 201911) + 1
# Daylight Saving Time in the EU in 2019 began on the last Sunday in March,
# which was on:
last_dw_in_month(7, 201903)
# International Monetary Market dates in 2022 - 3rd Wednesday
# of March, June, September, and December
nth_dw_in_month(3, 3, tind(y = 2022, m = 3 * 1:4))
# determine frequencies of Easter months over the last 100 years
# Easter months
em <- month(easter(as.year(today()) + (-99:0)), labels = TRUE)
# table and barplot
table(em) / length(em) * 100
if (require("graphics", quietly = TRUE)) {
barplot(table(em) / length(em) * 100, ylim = c(0, 100), col = "#faf06d")
}
Current Date and Time
Description
today returns the current date and now returns the current
date and time (in the system time zone or the time zone provided by the user).
Usage
today(tz = NULL)
now(tz = NULL, digits = 0)
Arguments
tz |
(optional) a character value determining the time zone (the default
|
digits |
an integer value giving the number of decimal places for seconds (0–6, 0 by default). |
Value
today and now return an object of class tind
of length 1 and type "d" (date) and "t" (date-time),
respectively.
Examples
today()
now()
# millisecond accuracy
now(digits = 3)
# check current date and time in different time zones
if ("Asia/Tokyo" %in% OlsonNames()) {
now("Asia/Tokyo")
today("Asia/Tokyo")
}
if ("Europe/Warsaw" %in% OlsonNames()) {
now("Europe/Warsaw")
today("Europe/Warsaw")
}
if ("America/New_York" %in% OlsonNames()) {
now("America/New_York")
today("America/New_York")
}
Group Time Indices into Periods / Convert to a Factor
Description
cut method for objects of tind class allows to map / group
time indices into periods. The periods can be determined based on indices
provided by the user or by (multiples of) units of time.
Usage
## S3 method for class 'tind'
cut(x, breaks, labels = TRUE, right = FALSE, ...)
Arguments
x |
an object of |
breaks |
a numeric value or a character string determining intervals,
or an object of |
labels |
a logical value controlling the return type, which
can be a factor (if |
right |
a logical value determing whether indices should be matched to the closest left cut point or to the closest right cut point, see Details. |
... |
(ignored) further arguments passed to or from other methods. |
Details
breaks argument controls how indices are grouped. It can be a number
or a character string determining resolution (or an object of tdiff class).
Alternatively, breaks can be an object of tind class with cut points.
When breaks determines resolution, only selected multiples of units
are allowed, similarly to floor_t function. Documentation of admissible
units and multiples can be found in Details section of resolution_t
method documentation. If selected resolution corresponds to an index of different
type (for example grouping dates to 2-month periods), conversion takes place.
This method differs from cut.POSIXt and cut.Date
in two aspects. Firstly, the periods are selected differently, they are always
aligned to resolution, see Examples. Secondly, as it does not rely
on seq but rounding of indices, the levels may be discontinuous. If users want
to replicate behaviour of cut from base, they should provide tind
constructed via seq.tind method as breaks argument.
When breaks is a tind object, it is expected to be sorted
without NAs. By default, indices in x
are matched to the closest index to the left (largest index that is not greater
than the argument). If right is set to TRUE, indices are matched
to the closest index to the right (smallest index that is not smaller than
the argument). right cannot be set to TRUE if breaks
is not a tind. It is acceptable that breaks is of lower resolution
than x provided that x is convertible to it. In such situations,
right cannot be set to TRUE.
By default, cut.tind returns a factor with levels created using
as.character method. If labels argument is set
to FALSE, only the integer vector (of the same length as argument)
of mappings to intervals is returned (as in base method).
If set to NA, a 2-element list is returned, with integer vector
of mappings as the first element and time indices determining intervals
(grouping, levels) as the second.
labels can only take TRUE/FALSE/NA values.
Value
A factor if labels is TRUE, an integer vector if FALSE,
and a 2-element list if NA, see Details.
See Also
rounding and resolution_t for description
of admissible units and multiples that can be used for breaks argument.
match_t for matching time indices to other indices and time
intervals.
Examples
# basic use
(d <- seq.tind("2023-09-14", "2023-12-16"))
cut(d, "15d")
cut(d, "m")
cut(d, "2m")
# tind given as breaks
cut(d, as.date(c("2023-09-01", "2023-11-16", "2023-12-16")))
cut(d, seq.tind("2023-01", "2023-12"))
# random order with NAs
(d <- sample(c(d, NA)))
cut(d, "15d")
cut(d, "m")
cut(d, "2m")
# different behaviour of cut for tind and Date (alignment to 2 month resolution,
# which means Jan, Mar, May, Jul, Sep, Nov)
(d <- seq.tind("2023-12-16", "2024-03-01"))
cut(d, "2 months")
cut(as.Date(d), "2 months")
# replicate behviour of cut.Date by providing sequence of months
cut(d, seq.tind("2023-12", "2024-03", by = "2m"))
# same
cut(d, seq.tind(as.month(min(d)), as.month(max(d)), by = "2m"))
# check
all.equal(cut(as.Date(d), "2 months", labels = FALSE),
cut(d, seq.tind("2023-12", "2024-03", by = "2m"), labels = FALSE))
Conversion between Dates and Their Integer Representations
Description
date2num and num2date support conversion between
tind dates and integer representations of dates (days since ...)
found in different software packages.
Usage
date2num(x, format)
num2date(x, format)
Arguments
x |
a |
format |
a character value determing numeric representation of date;
currently, the following are supproted: |
Value
date2num returns an integer vector
and num2date returns tind representing dates.
See Also
jdn for description of Julian Day Numbers.
Examples
(td <- today())
fmts <- c("R", "MATLAB", "Excel", "SAS", "JDN")
(n <- sapply(fmts, function(fmt) date2num(td, fmt)))
lapply(fmts, function(fmt) num2date(n[fmt], fmt))
Construct Date-Time Indices from Date and Time Components
Description
date_time can be used to create date-time indices from its components:
date and time of day (hour, minute, and second).
date_time_split performs the opposite computation: given date-time
indices, it returns a two-element list with vectors of dates and times.
Usage
date_time(d, H, M, S, tz = NULL, grid = FALSE)
date_time_split(x)
Arguments
d |
an object of |
H |
a numeric vector with hour values or an R object coercible to
time index of time-of-day type (type |
M |
(optional) a numeric vector with minutes. |
S |
(optional) a numeric vector with seconds. |
tz |
(optional) a character value determining the time zone (the default
|
grid |
a logical value, if |
x |
an object of |
Details
If arguments of date_time are of different length, they are recycled.
When grid is set to TRUE, date-time indices are constructed
from all combinations of dates and times in a way similar to how
functions expand.grid and kronecker work, see Examples.
If H argument is numeric, time of day is constructed from H,
M, and S arguments. In the last step date and time are combined
in order to construct date-time index. If H is not numeric,
M and S should not be supplied and time of day is constructed
from H argument only.
When provided without H argument date_time behaves just like
as.date_time i.e. returns the beginning of a day.
When an hour occurs twice in a day (due to DST/UTC offset changes),
the second occurrence is selected with a warning. When hour is missing
(for the same reason), NA is returned with a warning. See Examples.
Value
date_time returns an object of tind class
with date-time indices (type "t"). date_time_split
returns a two-element list with vectors of dates ($date) and times ($time).
See Also
tind constructor, time-index-components,
tzone.
Examples
date_time(today() + (0:1), "11:25:20.75")
date_time(today() + (0:1), as.time("11:25:20.75"))
date_time(today() + (0:1), 11, 25, 20.75)
date_time(today() + (0:1), "11:25:20")
date_time(today() + (0:1), 11, 25, 20)
date_time(today() + (0:1), "11:25")
date_time(today() + (0:1), 11, 25)
date_time(today() + (0:1), "11")
date_time(today() + (0:1), 11)
date_time(today() + (0:1))
# using 'grid' argument
date_time(today() + 0:2, c(8, 12, 16))
date_time(today() + 0:2, c(8, 12, 16), grid = TRUE)
# split date-time
(nw <- now())
date_time_split(nw)
# corner cases (with warnings)
if ("Europe/Warsaw" %in% OlsonNames()) try({
# 2020-10-25 had 25h with 02:00 repeated
date_time("2020-10-25", 0:2, tz = "Europe/Warsaw")
})
if ("Europe/Warsaw" %in% OlsonNames()) try({
# 2021-03-28 had 23h with 02:00 missing
date_time("2021-03-28", 0:2, tz = "Europe/Warsaw")
})
Differences Between Dates as Year Fractions / Accrual Factors
Description
This function computes difference between two dates as year fraction given day count convention.
Usage
daycount_frac(d1, d2, convention)
Arguments
d1 |
an object of |
d2 |
an object of |
convention |
a chacter string determining day count convention to be used, see Details. |
Details
Currently, the following day count conventions are supported:
30/360also known as 30/360 Bond Basis or 360/360, described in ISDA 2006 Section 4.16(f). The formula is as follows:
\frac{360(y_2-y_1) + 30(m_2-m_1) + (d_2-d_1)}{360},where
ydenotes year,mmonth,dday of month. Dates are adjusted accoring to the following rules: ifd_1is 31, it is changed to 30, ifd_2is 31 andd_1is 30 or 31,d_2is changed to 30.30E/360also known as Eurobond basis, 30/360 ICMA or 30/360 ISMA, described in ICMA Rule 251.1(ii), 251.2 and ISDA 2006 Section 4.16(g). The formula used is the same as above but the adjustment of dates is different: if
d_1ord_2is 31, it is changed to 30.ACT/ACTalso known as Actual/Actual and Actual/Actual ISDA, described in ISDA 2006 Section 4.16(b). Days between the dates (start included, end excluded) are divided into two groups: falling in leap and non-leap years. The number of days in leap years is divided by 366, the number of days in non-leap years is divided by 365. Finally, the two fractions are added.
ACT/365Falso known as Actual/365 Fixed, described in ISDA 2006 Section 4.16(d). Difference in days between dates divided by 365.
ACT/360also known as Actual/360, described in ISDA 2006 Section 4.16(e). Difference in days between dates divided by 360.
Value
A numeric vector.
References
International Swaps and Derivatives Association, Inc., 2006 ISDA Definitions, New York, 2006.
See Also
Examples
daycount_frac("2023-01-29", "2023-03-31", "30/360")
1/6 + 2/360
daycount_frac("2023-01-29", "2023-03-31", "30E/360")
1/6 + 1/360
daycount_frac("2023-01-29", "2023-03-31", "ACT/ACT")
61 / 365
daycount_frac("2024-01-29", "2024-03-31", "ACT/ACT")
62 / 366
daycount_frac("2023-01-29", "2023-03-31", "ACT/365F")
61 / 365
daycount_frac("2024-01-29", "2024-03-31", "ACT/365F")
62 / 365
daycount_frac("2023-01-29", "2023-03-31", "ACT/360")
61 / 360
daycount_frac("2024-01-29", "2024-03-31", "ACT/360")
62 / 360
Lagged Differences for tind and tdiff Objects
Description
diff method for tind and tdiff works in a standard way.
For all index types except for integer and numeric indices, differences
of time indices are retuned as objects of tdiff class.
Usage
## S3 method for class 'tind'
diff(x, lag = 1L, differences = 1L, ...)
## S3 method for class 'tdiff'
diff(x, lag = 1L, differences = 1L, ...)
Arguments
x |
an object of |
lag |
an integer value. |
differences |
an integer value. |
... |
(ignored) further arguments passed to or from other methods. |
Value
An object of tdiff class, except for x argument
of tind class of type "i" or "n" (integer/numeric
indices), in which case an integer or numeric vector is returned.
See Also
Ops.
Examples
(nn <- sample(1:10))
(x <- today() + nn)
# all 3 should be the same
diff(x, 2, 2)
as.tdiff(diff(nn, 2, 2), "d")
diff(as.tdiff(nn, "d"), 2, 2)
Conversion between Objects of tind Class and Character Vectors
Description
format method converts objects of tind class to character
vectors given format and locale information. strptind function
accepts character vector with time indices and parses to create object
of tind class.
Usage
## S3 method for class 'tind'
format(x, format, locale = NULL, ...)
strptind(x, format, locale = NULL, type = NULL, tz = NULL)
Arguments
x |
an object to be converted, a character vector for |
format |
a character string or character vector determining string format(s) (see Details). |
locale |
a character value determining locale to be used for |
... |
(ignored) further arguments passed to or from other methods. |
type |
(optional) a character value determining time index type. |
tz |
(optional) a character value determining the time zone (the default
|
Details
Names of accepted format specifiers except for %q are conformant
with those used by format.Date, format.Date
and strptime. Accepted specifiers are listed below:
%aAbbreviated weekday name.
%AWeekday name.
%bAbbreviated month name.
%BMonth name.
%dDay of month (01–31).
%eDay of month (1–31) with a leading space for a single-digit number.
%DAmerican/C99 date representation
%m/%d/%y.%FISO 8601 date
%Y-%m-%d.%gThe last two digits of the week-based year.
%GThe week-based year.
%HHour (00–23).
%IHour, 12-hour clock (1–12).
%pAM/PM indicator.
%jDay of year (001–366).
%mMonth (01–12).
%MMinute (00–59).
%nNewline.
%OS[n]Second with
n(0–6) decimal places.%OSSecond with up to 6 decimal places (automatically detected precision during parsing).
%q(Not supported by base R.) Quarter (1–4).
%RSame as
%H:%M.%SSecond (00–59), leap seconds are not accepted on input.
%tTab or whitespace.
%TSame as
%H:%M:%S.%uWeekday (1–7) with Monday as the first day in a week (ISO 8601).
%VWeek (01–53) as defined in ISO 8601.
%y2-digit year (00–99), values 00–68 are prefixed by 20 and 69–99 by 19.
%Y4-digit year (0–9999), 0 is allowed by ISO 8601.
%zSigned offset in hours and minutes from UTC, accepted input formats are
+-HHMM,+-HH,+-HH:MM, and letterZfor UTC.%ZTime zone abbreviation (also supported on input).
On very rare occasions (the need to use formats unsupported by strptind)
users will have to call strptime and then as.tind
method or perform some regex preprocessing before calling strptind.
type argument is optional as strptind automatically determines
index type from components. However, it can be set as a safeguard against format
misspecifications.
Value
strptime returns an object of tind class, format
returns a character vector.
Note
The following strptime specifiers (as well as some others)
are not supported (most often because they are locale specific or do not
comply with ISO 8601):
%cLocale-specific date and time.
%CCentury (00–99).
%hEquivalent to
%b.%r12-hour clock time using AM/PM indicator.
%UWeek of the year (US convention).
%wWeekday (0–6).
%WWeek of the year (UK convention).
%xLocale-specific date.
%XLocale-specific time.
See Also
parse_t for easier to use index parsing requiring
order specification only, calendar-names for information on locale settings.
Examples
## years
# four-digit year
(ti <- strptind(as.character(1998:2002), "%Y"))
format(ti, "%Y")
# two-digit year
(ti <- strptind(c("98", "99", "00", "01", "02"), "%y"))
format(ti, "%y")
# mixture of four-digit and two-digit years
strptind(c("1998", "1999", "00", "01", "02"), c("%Y", "%y"))
## quarters
(ti <- strptind(c("2020Q1", "2020Q2", "2020Q3", "2020Q4"), "%YQ%q"))
format(ti, "%YQ%q")
format(ti, "%Yq%q")
format(ti, "%Y.%q")
## months
(ti <- strptind(c("2020-03", "2020-06", "2020-09", "2020-12"), "%Y-%m"))
format(ti, "%Y-%m")
(ti <- strptind(c("03/20", "06/20", "09/20", "12/20"), "%m/%y"))
format(ti, "%m/%y")
format(ti, "%b '%y")
## weeks
(ti <- strptind(c("2020-W01", "2020-W05", "2020-W09", "2020-W13"), "%G-W%V"))
format(ti, "%G-W%V")
format(ti, "%G, week: %V")
strptind(c("2020, week: 13"), "%G, week: %V")
## dates
# ISO format
(ti <- strptind(c("2025-03-19", "2025-06-18", "2025-09-17", "2025-12-17"), "%F"))
format(ti, "%F")
strptind(c("2025-03-19", "2025-06-18", "2025-09-17", "2025-12-17"), "%Y-%m-%d")
format(ti, "%Y-%m-%d")
# US format
strptind(c("03/19/25", "06/18/25", "09/17/25", "12/17/25"), "%D")
format(ti, "%D")
strptind(c("03/19/25", "06/18/25", "09/17/25", "12/17/25"), "%m/%d/%y")
format(ti, "%m/%d/%y")
# European format
strptind(c("19.03.2025", "18.06.2025", "17.09.2025", "17.12.2025"), "%d.%m.%Y")
format(ti, "%d.%m.%Y")
# mixed formats
strptind(c("03/19/25", "06/18/25", "17.09.2025", "17.12.2025"),
c("%m/%d/%y", "%d.%m.%Y"))
strptind(c("03/19/25", "06/18/25", "2025-09-17", "2025-12-17"),
c("%D", "%F"))
## time of day
(ti <- strptind("13:03:34.534", "%H:%M:%OS"))
format(ti, "%H:%M:%OS3")
format(ti, "%H:%M:%OS2")
format(ti, "%H:%M:%OS1")
strptind("13:03:34", "%H:%M:%S")
format(ti, "%H:%M:%S")
strptind("13:03", "%H:%M")
format(ti, "%H:%M")
strptind("13", "%H")
format(ti, "%H")
strptind("01:03:44 pm", "%I:%M:%S %p")
format(ti, "%I:%M:%S %p")
strptind("1:03:44 pm", "%I:%M:%S %p")
strptind(c("1am", "1pm"), "%I%p")
## date-time
(ti <- strptind("2025-02-01 13:03:34.534", "%F %H:%M:%OS"))
format(ti, "%F %H:%M:%S")
format(ti, "%F %H:%M:%OS2")
format(ti, "%F %H:%M:%S%z")
format(ti, "%F %H:%M:%OS2 %Z")
strptind("02/01/25 01:03:34pm", "%D %I:%M:%OS%p")
Date and Date-Time Conversion to and from Julian Day Number (JDN)
Description
jdn computes the JDNs for dates or date-time indices and
jdn2tind returns dates or date-time indices given JDNs.
For date arguments jdn returns the numbers of days
since November 24, 4714 BC in the proleptic Gregorian calendar as
an integer vector. For date-time arguments day fraction in UTC is computed
and the return value is a numeric vector.
For integer arguments jdn2tind return tind of type
"d" (date), for non-integer arguments — tind of type
"t" (date-time). If tz argument is provided the return value
is always of type "t" (date-time).
Usage
jdn(x)
jdn2tind(x, tz = NULL)
Arguments
x |
an object of |
tz |
(optional) a character value determining the time zone (the default
|
Value
An integer or numeric vector for jdn, an object of tind class
(type "d" or "t") for jdn2tind.
Note
For date-time indices JDN is computed based on day fraction since noon UTC and not midnight, so 0.5 offset will be observable.
See Also
date2num for conversion between dates and their
integer representations found different software packages.
Examples
# JDN of 2000-01-01 is 2451545
jdn("2000-01-01")
jdn2tind(2451545)
# JDN today, now?
jdn(today())
jdn(now())
# notice the .5 offset
jdn(today(tz = "UTC"))
format(jdn(as.date_time(today(tz = "UTC"), tz = "UTC")), digits = 8)
Matching Time Indices
Description
match_t and %in_t% allow for matching time indices
to time intervals and to other sets of time indices including cases when
table argument is of different type than x (of lower resolution).
Usage
match_t(x, table, nomatch = NA_integer_)
x %in_t% table
Arguments
x |
an object of |
table |
an object of |
nomatch |
an integer value to be returned when no match is found. |
Details
%in_t% always returns TRUE/FALSE. NAs
in x argument are never matched (FALSE is returned).
Value
match_t and %in_t% return integer and logical vectors,
respectively. The length of the result equals length of x.
Note
Since match and %in% are not implemented in base as
S3 generics, new functions had to be implemented.
Examples
# match dates to months
(x <- as.date("2025-03-02") + 15 * (0:5))
(table <- as.month("2025-03") + -1:1)
match_t(x, table)
# match dates to time intervals representing months
(table <- (as.date("2025-03-01") %--% as.date("2025-03-31")) %+m% (-1:1))
match_t(x, table)
# are dates in March 2025?
x %in_t% "2025-03"
# NAs are _never_ matched
(x <- as.date("2025-03-02") + c(NA, 15 * (0:5)))
(table <- as.month("2025-03") + c(NA, -1:1))
match_t(x, table)
x %in_t% table
Merging Time-indexed Data
Description
merge method for tind allows to join two (or more) time-indexed
datasets also in cases when the indices are of different types. The method
is intended for advanced users.
The method takes two tind vectors (x and y) and returns
a three-element list containing resulting indices and mappings (integer
indices) from the original indices to the final ones allowing to select
appropriate rows from dataset indexed by x and y, see Examples.
Usage
## S3 method for class 'tind'
merge(x, y, ..., all = FALSE, all.x = all, all.y = all)
Arguments
x, y |
an object of |
... |
(optional) further time indices. |
all |
a logical value, equivalent to setting both |
all.x |
a logical value, if |
all.y |
a logical value, analogous to |
Details
By default (all = FALSE), inner join is performed. x and y
can be indices of different types but conversion of the higher resolution
to the lower should be possible.
If all.x = TRUE, left join is performed. All indices from x
are preserved. y can then be of the same or lower resolution than x.
If all.y = TRUE, right join is performed. All indices from y
are preserved. x can then be of the same or lower resolution than y.
If all = TRUE, outer join is performed. All indices from x
and y are preserved. Indices in x and y have to be
of the same type in this case.
Setting all argument silently overrides both all.x and all.y.
NAs are never matched.
The method is optimized in case both indices are strictly increasing without
NAs (time series applications). In other cases, it employs
merge method for specially constructed data frames.
The method also accepts more than two arguments (time indices). In this case,
it is expected that all are strictly increasing without NAs (time
series applications only). all.x and all.y cannot be used
with more than two arguments.
all can be a vector of logical values indicating which indices have
to always be included in the result (TRUE) and which have to be
matched (FALSE). In 2-argument case, for example, all = c(TRUE, FALSE)
is equivalent to all.x = TRUE and all = c(FALSE, TRUE)
to all.y = TRUE.
Value
A three-element list with the first element (index) containing
the final time indices, and the remaining two (xi and yi)
mappings from x and y to these indices. If additional time
indices are provided, the length of the returned list equals the number of
all arguments (including x and y) plus one (for the final index
at the beginning of the list).
See Also
match_t for matching time indices.
Examples
# construct sample data frames
(dates1 <- tind(y = 2023, m = rep(1:4, each = 2), d = c(1, 16)))
(dates2 <- dates1 %+m% 1)
(mnths <- as.month("2022-12") + 0:3)
(df1 <- data.frame(dates1, nd1 = as.numeric(dates1),
downame = day_of_week(dates1, labels = TRUE, abbreviate = FALSE)))
(df2 <- data.frame(dates2, nd2 = as.numeric(dates2), dow = day_of_week(dates2)))
(df3 <- data.frame(mnths, nm = as.numeric(mnths),
mname = month(mnths, labels = TRUE, abbreviate = FALSE)))
# inner join - dates
(mti <- merge(df1[[1L]], df2[[1L]]))
data.frame(index = mti[[1L]],
df1[mti[[2L]], -1L, drop = FALSE],
df2[mti[[3L]], -1L, drop = FALSE])
# inner join - dates and months
(mti <- merge(df1[[1L]], df3[[1L]]))
data.frame(index = mti[[1L]],
df1[mti[[2L]], -1L, drop = FALSE],
df3[mti[[3L]], -1L, drop = FALSE])
# left join - dates
(mti <- merge(df1[[1L]], df2[[1L]], all.x = TRUE))
data.frame(index = mti[[1L]],
df1[mti[[2L]], -1L, drop = FALSE],
df2[mti[[3L]], -1L, drop = FALSE])
# left join - dates and months
(mti <- merge(df1[[1L]], df3[[1L]], all.x = TRUE))
data.frame(index = mti[[1L]],
df1[mti[[2L]], -1L, drop = FALSE],
df3[mti[[3L]], -1L, drop = FALSE])
# right join - dates
(mti <- merge(df1[[1L]], df2[[1L]], all.y = TRUE))
data.frame(index = mti[[1L]],
df1[mti[[2L]], -1L, drop = FALSE],
df2[mti[[3L]], -1L, drop = FALSE])
# right join - months and dates
(mti <- merge(df3[[1L]], df2[[1L]], all.y = TRUE))
data.frame(index = mti[[1L]],
df3[mti[[2L]], -1L, drop = FALSE],
df2[mti[[3L]], -1L, drop = FALSE])
# outer join - dates
(mti <- merge(df1[[1L]], df2[[1L]], all = TRUE))
data.frame(index = mti[[1L]],
df1[mti[[2L]], -1L, drop = FALSE],
df2[mti[[3L]], -1L, drop = FALSE])
Working with Ordered and Regularly Spaced Time Indices
Description
is.ordered_t method checks if time indices form a strictly
increasing sequence without NA values.
is.regular method checks if time indices form a strictly
increasing, regularly spaced sequence without NA values.
as.regular returns regularly spaced sequence of time
indices based on strictly increasing time indices provided.
extend_regular extends strictly increasing sequence of time indices
by n points after the last taking into account the resolution
of the sequence provided.
Usage
is.ordered_t(x)
## S3 method for class 'tind'
is.ordered_t(x)
is.regular(x)
## S3 method for class 'tind'
is.regular(x)
as.regular(x, ...)
## S3 method for class 'tind'
as.regular(x, ...)
extend_regular(x, n)
Arguments
x |
an object of |
... |
further arguments passed to or from other methods. |
n |
an integer value, number of time stamps to be added, see Details. |
Details
n argument of extend_regular can be negative. In that case
-n points are added before the first index. The function may
fail in corner cases (if the result would be out of range).
Creating regular date-time sequences in front of DST/UTC offset changes can be impossible. If the algorithm fails, an error is issued. In general, this should not be a problem when DST change is by 1 hour and the resolution of the indices is 1 hour or higher.
Value
A logical value for is.ordered_t and is.regular.
An object of tind class for as.regular and extend_regular.
See Also
resolution_t method.
Examples
# months, resulution 2m
(ms <- tind(y = 2023, m = 1 + 2 * (0:5)))
is.regular(ms)
extend_regular(ms, 3)
(ms <- tind(y = 2023, m = c(1, 3, 5, 9)))
is.regular(ms)
as.regular(ms)
# date, resulution 15d
(ds <- tind(y = 2024, m = rep(1:3, each = 2), d = c(1, 16)))
is.regular(ds)
extend_regular(ds, -4)
(ds <- ds[-2L])
is.regular(ds)
as.regular(ds)
# corner cases
tz <- "Europe/Warsaw"
if (tz %in% OlsonNames()) {
# switch to DST
print(hours_in_day("2025-03-30", tz = tz))
# this will work with step from 1am to 3am
tt <- date_time("2025-03-30", H = c(0, 4:8), tz = tz)
print(resolution_t(tt))
as.regular(tt)
}
if (tz %in% OlsonNames()) {
# this will fail due to missing 2am
tt <- date_time("2025-03-30", H = c(0, 4, 6, 8), tz = tz)
print(resolution_t(tt))
try(as.regular(tt))
}
if (tz %in% OlsonNames()) {
# this will work again (step by 4h)
tt <- date_time("2025-03-30", H = c(0, 4, 12), tz = tz)
print(resolution_t(tt))
as.regular(tt)
}
Parse Character Representation of Time Indices Given the Order of Components
Description
parse_t parses character vector to create an object of tind
class based on provided order(s) of time index components. Index type is inferred
from components given.
Usage
parse_t(x, order, locale = NULL, type = NULL, tz = NULL)
Arguments
x |
a character vector of time indices to be parsed. |
order |
a character string or a character vector describing order(s) of time
index components in the input ( |
locale |
(optional) a character value determining locale or |
type |
(optional) a character value determining time index type. |
tz |
(optional) a character value determining the time zone (the default
|
Details
Accepted names of components are:
yyear.
qquarter.
mmonth, number (1–12) or name.
dday.
jday of year.
wweek (01–53) as defined in ISO 8601.
uday of week, number (1–7 with Monday as the first day, ISO 8601) or name.
Hhour.
Ihour, 12-hour clock.
pAM/PM indicator.
Mminute.
Ssecond.
zUTC offset (
+-HHMM,+-HH,+-HH:MM, or letterZfor UTC) or time zone abbreviation (likeCETorCEST).
The following combinations of components (in any order) are accepted for different index types (whitespace between specifiers is ignored):
- year (type
"y"): y.- quarter (type
"q"): yandq.- month (type
"m"): yandm.- week (type
"w"): yandw.- date (type
"d"): y,m, andd;y, andj;y,w, andu.- time of day (type
"h"): at least hour component with optional minutes and seconds.
- date-time (type
"t"): any valid combination for date and at least hour component with optional minutes and seconds.
During parsing all non-digits are skipped in front of "y", "q",
"w", "d", "j", "H", "I", "M", "S"
specifiers and all non-alphanumeric characters are skipped in front of
"m", "u", "p". Only whitespace is ignored in front of "z"
specifier.
parse_t was inspired by ymd, mdy, etc. family of functions
from package lubridate but independently implemented from scratch
(and is a bit faster).
Value
An object of tind class.
See Also
strptind for index parsing requiring strict format
specification, calendar-names for information on locale settings.
Examples
## years
# four-digit year
parse_t(as.character(1998:2002), "y")
# two-digit year
parse_t(c("98", "99", "00", "01", "02"), "y")
# mixture of four-digit and two-digit years
parse_t(c("1998", "1999", "00", "01", "02"), "y")
## quarters
parse_t(c("2020Q1", "2020Q2", "2020Q3", "2020Q4"), "yq")
## months
parse_t(c("2020-03", "2020-06", "2020-09", "2020-12"), "ym")
parse_t(c("03/20", "06/20", "09/20", "12/20"), "my")
# missing leading zeros are also handled
parse_t(c("3/20", "6/20", "9/20", "12/20"), "my")
## weeks
# standard format
parse_t(c("2020-W01", "2020-W05", "2020-W09", "2020-W13"), "yw")
# non-standard format
parse_t(c("2020, week: 01", "2020, week: 05", "2020, week: 09", "2020, week: 13"), "yw")
# missing leading zeros are also handled
parse_t(c("2020, week: 1", "2020, week: 5", "2020, week: 9", "2020, week: 13"), "yw")
## dates
# ISO format
parse_t(c("2025-03-19", "2025-06-18", "2025-09-17", "2025-12-17"), "ymd")
# US format
parse_t(c("03/19/25", "06/18/25", "09/17/25", "12/17/25"), "mdy")
# missing leading zeros are handled
parse_t(c("3/19/25", "6/18/25", "9/17/25", "12/17/25"), "mdy")
# European format
parse_t(c("19.03.2025", "18.06.2025", "17.09.2025", "17.12.2025"), "dmy")
# mixed formats
parse_t(c("03/19/25", "06/18/25", "17.09.2025", "17.12.2025"), c("mdy", "dmy"))
parse_t(c("03/19/25", "06/18/25", "2025-09-17", "2025-12-17"), c("mdy", "ymd"))
## time of day
parse_t("13:03:34.534", "HMS")
parse_t("13:03:34", "HMS")
parse_t("13:03", "HM")
parse_t("13", "H")
parse_t("1:03:44 pm", "IMSp")
parse_t("1pm", "Ip")
## date-time
parse_t("2025-02-01 13:03:34.534", "ymdHMS")
parse_t("2025-02-01 13:03:34.534", "ymdHMS", tz = "UTC")
parse_t("02/01/25 01:03:34pm", "mdyIMSp")
parse_t("02/01/25 01:03:34pm", "mdyIMSp", tz = "UTC")
Pretty Breakpoints for Time Indices
Description
Determine locations of pretty breakpoints for time indices.
pretty method for objects of tind class employs separate
algorithms for each type / resolution, see Details.
Usage
## S3 method for class 'tind'
pretty(x, n = 5L, min.n = n%/%2L, ...)
Arguments
x |
an object of |
n |
an integer value giving the expected number of intervals. |
min.n |
an integer value giving the minimal number of intervals. |
... |
(ignored) further arguments passed to or from other methods |
Details
Resolution of ticks (see resolution_t method) is always the same or
lower than the resolution of the argument and lower resolutions have to be
multiples of the resolution of the argument. This way, the ticks are never
placed, for example, every 5 years for indices with a 2-year resolution.
For years, the tics are placed at powers of 10 times 1, 2, or 5.
For quarters, ticks are placed every quarter, every second quarter (1st and 3rd), or on first the quarters of years selected by separate procedure for years.
For months, ticks are placed every 1, 2, 3, 4, 6 months or on January of years selected by the separate procedure for years.
For weeks, ticks are placed every 1, 2, 4, 13, 26 weeks or on the first weeks of years selected by the separate procedure for years.
For dates, depending on the number of observations, ticks can be placed:
every day,
every Monday, Wednesday, and Friday,
every Monday and Thursday,
every Monday,
every 1st and 16th day of a month,
on 1st days of months selected by the separate procedure for months.
For date-time and time of day, the placement of ticks depends on the resolution of indices. When all indices are at full hours, ticks are placed at full hours only. Similar approach is taken for minutes and seconds. Divisors of 24 are used for hours and divisors of 60 for minutes and seconds. For date-time indices spanning more than a couple of days, ticks are placed on midnights of days selected by the separate procedure for dates.
Due to the design of the algorithm, in some corner cases (esp. for time of
day and weeks) the number of intervals might differ significantly from
the expected number n.
Value
An object of tind class.
See Also
resolution_t method, axis_t for computing
time axis parameters for plotting, axis.tind for creating axes
with graphics package, scale_tind for creating axes
with ggplot2.
Examples
(td <- tind(y = sample(2010:2018, 4, replace = TRUE),
m = sample(1:12, 4, replace = TRUE),
d = sample(1:2, 4, replace = TRUE)))
pretty(td)
pretty(td, 3)
pretty(td, 10)
(th <- tind(H = sample(0:23, 4, replace = TRUE),
M = sample(0:3 * 15, 4, replace = TRUE)))
pretty(th)
pretty(th, 3)
pretty(th, 10)
(tdt <- date_time(td[1], th))
pretty(tdt)
pretty(tdt, 3)
pretty(tdt, 10)
Determine the Resolution of Time Indices
Description
resolution_t method determines resolution of time indices.
For time index types other than integer index ("i") and numeric index
("n"), resolution_t returns an object of tdiff class.
The following multiples of units can be returned by resolution_t method:
"y"(years):1, 2, 5, 10, 20, 50, 100, 200, 500, 1000.
"q"(quarters):1, 2.
"m"(months):1, 2, 3, 4, 6.
"w"(weeks):1, 2, 4, 13, 26.
"d"(days):1, 15 (1st and 16th day of a month).
"h"(hours):1, 2, 3, 4, 6, 8, 12.
"min"(minutes):1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30.
"s"(seconds):1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 and 1, 2, or 5 times negative powers of 10.
Basic resolution (1) for given type is always returned for vectors with 1 or no
non-NA value.
An integer value is returned for type "i" (integer index) and
a numeric value (possibly NA_real_) for type "n" (numeric index).
Usage
resolution_t(x)
## S3 method for class 'tind'
resolution_t(x)
Arguments
x |
an object of |
Value
For all types except for integer index ("i") and numeric index
("n") resolution_t returns an object of tdiff class.
An integer value for type "i" (integer index) and a numeric value
(possibly NA_real_) for type "n" (numeric index) are returned.
See Also
rounding for rounding time indices to specified resolution,
is.regular method for checking if time indices form a regular
sequence, tspan method for determining time span of indices.
Examples
(ds <- tind(y = 2024, m = rep(1:3, each = 2), d = c(1, 16)))
resolution_t(ds)
(ms <- tind(y = 2023, m = 1 + 2 * (0:5)))
resolution_t(ms)
(th <- tind(H = 13, M = (0:3) * 15))
resolution_t(th)
(dt <- tind(y = 2025, m = 2, d = 1, H = 13, M = 27, S = (0:5) * 10))
resolution_t(dt)
Rounding Time Indices
Description
Time indices can be rounded to different time units (depending on the type of time index at hand, see Details).
trunc_t rounds the indices down to a given unit
with change of index type where applicable.
floor_t rounds the indices down to a (multiple of a) unit.
ceiling_t rounds the indices up to a (multiple of a) unit.
round_t rounds the indices to the closest multiple of a unit, i.e.
the result of floor_t or ceiling_t, whichever is closer.
Usage
trunc_t(x, unit)
floor_t(x, unit)
ceiling_t(x, unit, ceiling = c("default", "following", "last"))
round_t(x, unit, ceiling = c("default", "following", "last"))
Arguments
x |
an object of |
unit |
a character string determining unit (expected by |
ceiling |
(optional) a character string determining the behaviour
of |
Details
Units and Unit Multiples
For trunc_t, unit has to be a character string determining
resolution / type to which indices should be truncated. For the remaining
functions, unit argument can be a number (the default unit for index
type will be used), a character string with unit name, an object
of tdiff class, or a character string with a number and unit name.
The following unit names are accepted:
"y","year","years"years,
"q","quarter","quarters"quarters,
"m","mon","month","months"months,
"w","week","weeks"weeks,
"d","day","days"days,
"h","hour","hours"hours,
"min","minute","minutes"minutes,
"s","sec","second","seconds"seconds.
The default unit for date-time and time of day indices is a second.
The list of admissible multiples of units can be found in the documentation
of resolution_t method.
For time indices of types "i" and "n" (integer and numeric indices)
unit can be any finite, positive integer / numeric value.
In case of a tie (x - floor_t(x, *) equal to ceiling_t(x, *) - x),
round_t returns the result of ceiling_t.
Controlling behaviour of ceiling_t (and round_t)
For non-instant time indices, i.e indices that actually represent periods of time
(days weeks, months, etc.) ceiling_t rounds to the first index in a period
by default. For instance, when rounding dates to months, the first day of a month
will be unchanged and other days will be rounded to the first day in the
following month. This behaviour can be altered by setting ceiling
argument. If set to "following", the first index (day in our example)
in the following period will be returned. If set to "last", the last
index (day in our example) in the period will be returned. See Examples.
Value
An object of tind class of the same type and length as x
except for trunc_t, for which the type of the result is determined
based on unit argument.
Note
Methods floor, ceiling, round, and trunc are
not implemented for tind class due to generics' argument list
limitations.
See Also
resolution_t method.
Examples
(d <- as.tind("2024-08-27"))
floor_t(d, "w")
trunc_t(d, "w")
ceiling_t(d, "w")
round_t(d, "w")
floor_t(d, "m")
trunc_t(d, "m")
ceiling_t(d, "m")
round_t(d, "m")
floor_t(d, "3m")
ceiling_t(d, "3m")
round_t(d, "3m")
(dt <- as.tind("2024-08-27 13:51:52"))
floor_t(dt, 10)
floor_t(dt, "10s")
ceiling_t(dt, "10s")
round_t(dt, "10s")
floor_t(dt, "min")
trunc_t(dt, "min")
ceiling_t(dt, "min")
round_t(dt, "min")
floor_t(dt, "h")
trunc_t(dt, "h")
ceiling_t(dt, "h")
round_t(dt, "h")
floor_t(dt, "2h")
ceiling_t(dt, "2h")
round_t(dt, "2h")
floor_t(dt, "d")
trunc_t(dt, "d")
ceiling_t(dt, "d")
round_t(dt, "d")
# corner cases - DST change (02:00 missing)
(dt <- date_time("2025-03-30", H = c(0:1, 3:6)))
floor_t(dt, "2h")
ceiling_t(dt, "2h")
# adjusting behaviour of ceiling_t for non-instant time indices
# a short sequence of dates covering two months
(ds <- as.tind("2023-01-01") + -2:2)
# default behaviour
ceiling_t(ds, "2m")
ceiling_t(ds, "2m", ceiling = "default")
# round up to the first day in the following 2-month period
ceiling_t(ds, "2m", ceiling = "following")
# round up to the last day in the current 2-month period
ceiling_t(ds, "2m", ceiling = "last")
# a corner case, note that we will get the next day as a result
ceiling_t(today(), "1d", ceiling = "following")
Time Scales for Plotting with ggplot2
Description
These functions provide ggplot2 scales for tind. Scales will
be added automatically by ggplot2, but the default behaviour
can be overridden by adding scale_*_tind to the plot.
Usage
scale_x_tind(
name = ggplot2::waiver(),
breaks = ggplot2::waiver(),
minor_breaks = ggplot2::waiver(),
n.breaks = 7L,
labels = ggplot2::waiver(),
limits = NULL,
expand = ggplot2::waiver(),
guide = ggplot2::waiver(),
position = "bottom",
format = NULL,
locale = NULL
)
scale_y_tind(
name = ggplot2::waiver(),
breaks = ggplot2::waiver(),
minor_breaks = ggplot2::waiver(),
n.breaks = 7L,
labels = ggplot2::waiver(),
limits = NULL,
expand = ggplot2::waiver(),
guide = ggplot2::waiver(),
position = "left",
format = NULL,
locale = NULL
)
Arguments
name |
a character string with axis name, |
breaks |
|
minor_breaks |
|
n.breaks |
an integer value, desired number of breaks. |
labels |
|
limits |
|
expand, guide |
see scale_continuous. |
position |
a character string determining axis position,
|
format |
(optional) a character string determining label format
(see |
locale |
(optional) a character string determining locale to be used for formatting labels, see calendar-names for information on locale settings. |
Details
The algorithm determining positioning of breaks and minor breaks always takes
the resolution of time indices (see resolution_t) into account.
For example, for monthly data with breaks placed every three months (January,
April, July, October) minor breaks will never be placed in the middle (mid of
February, May, August, November) but rather every month. The algorithm
overrides the default approach of ggplot2 — axis limits are determined
based on breaks and breaks on time indices and their resolution, whereas
ggplot2 starts with limits based on data and determines breaks based
on limits only (ignoring the resolution of time indices).
Argument list is a bit different from that of to scale_*_date and
scale_*_datetime. Firstly, n.breaks argument is supported,
allowing users to set the expected number of breaks on time axis. Secondly,
labels cannot be a function. Formatting functions can be provided via
format argument, which also supports character string with format
specification (see format) rendering date_labels
argument redundant. locale argument controls the language used
for month and weekday names, see calendar-names.
breaks cannot be a function, but can be a tdiff / character string
determining distance between breaks rendering date_breaks argument
redundant. limits argument is expected to determine time interval
and not limits in Cartesian coordinates. Open-ended intervals are supported.
breaks, minor_breaks, and limits cannot be functions
as ggplot2 assumes that breaks and limits can be properly set based
on (automatic) limits only without taking into account the resolution of time
indices, which is not true.
Secondary axes are not supported.
Value
A continuous scale as returned by continuous_scale.
Note
Due to the fact that limits method is currently
(as of version 4.0.0) not exported, users cannot use xlim and
ylim with tind scales. Limits on time-indexed axes can be set
using limits argument to scale_*_tind.
See Also
pretty for computing pretty breakpoints,
axis_t for computing time axis parameters,
axis.tind for creating axes with graphics package.
Examples
# load ggplot2
library(ggplot2)
# artificial data
d <- seq(floor_t(today(), "y"), ceiling_t(today(), "y", ceiling = "last"))
df <- data.frame(d = d, D = as.Date(d), y = cumsum(rnorm(length(d))),
q = paste0("Q", quarter(d)))
# default scale
ggplot(df) + geom_line(aes(x = d, y = y)) + theme_bw()
# compare with the default scale for Date
ggplot(df) + geom_line(aes(x = D, y = y)) + theme_bw()
# change format
ggplot(df) + geom_line(aes(x = d, y = y)) + theme_bw() +
scale_x_tind(format = "%b '%y")
# set breaks every 4 months
ggplot(df) + geom_line(aes(x = d, y = y)) + theme_bw() +
scale_x_tind(breaks = "4m")
# set limits
ggplot(df) + geom_line(aes(x = d, y = y), na.rm = TRUE) + theme_bw() +
scale_x_tind(limits = c(today() %-m% 4, today()))
# facets with custom formatting and reduced number of breaks
ggplot(df) + geom_line(aes(x = d, y = y)) + theme_bw() +
scale_x_tind(n.breaks = 4, format = "%b '%y") +
facet_wrap(~q, scales = "free_x")
Create a Sequence of Time Indices
Description
seq method for objects of tind class allows to easily construct
sequences of time indices of all supported types.
Usage
## S3 method for class 'tind'
seq(from, to, by = 1, length.out = NULL, along.with = NULL, ...)
Arguments
from |
an object of |
to |
an object of |
by |
a numeric value, a |
length.out |
an integer value, the desired length. |
along.with |
any R object, length of this argument will be taken as the desired length. |
... |
(ignored) further arguments passed to or from other methods. |
Details
seq method requires that exactly two of the three arguments from,
to, and length.out are provided. If along.with is not
NULL, its length is used as value of length.out.
by can be a number, an object of tdiff class (of length 1), or an object
coercible to tdiff like "3w" denoting step by three weeks.
by cannot be NA and cannot be 0 when both from and to are
provided. Given both from and to, sign of by
has to agree with the order of from and to.
When by is a number, the underlying unit of time is assumed. For time of day
and date-time indices this is always a second.
from and to can be of different types provided that conversion is possible.
The result is of higher resolution. This allows to easily construct series like
from begging of the month to today, from today till the end of next year, etc.
See Examples.
seq.tind slightly differs from seq.Date
in terms of interface and requirements with respect to arguments.
Firstly, from argument can be missing (provided that to and
length.out are given). Secondly, by has the default value of 1.
Both seq method for tind and seq.tind function are
exported allowing for conversion to tind as in
seq.tind("2025-01", "2025-12").
Value
An object of tind class.
Examples
# sequences of dates by 1 and 2 months from now
(td <- today())
seq(td, by = "1m", length.out = 12)
seq(td, by = "2m", length.out = 6)
# sequences of dates by 1 and 2 months to now
seq(to = td, by = "1m", length.out = 12)
seq(to = td, by = "2m", length.out = 6)
# sequence of dates from the beginning of the month till today
seq(floor_t(td, "m"), td)
# same
seq(as.month(td), td)
# sequence of dates from today till the end of the next month
seq(td, as.month(td) + 1)
# sequence of date-time from now to midnight by 1 hour
(nw <- now())
seq(nw, ceiling_t(nw, "1d"), by = "1h")
# same
seq(nw, as.date(nw), by = "1h")
# sequence (date-time) from full hour to now by 2 minutes
seq(floor_t(nw, "1h"), nw, by = "2min")
# sequence (time of day) from full hour to now by 2 minutes
seq(floor_t(as.time(nw), "1h"), as.time(nw), by = "2min")
# sequence (date-time) from now down to full hour by 2 minutes
seq(nw, floor_t(nw, "1h"), by = "-2min")
# sequence (time of day) from now down to full hour by 2 minutes
seq(as.time(nw), floor_t(as.time(nw), "1h"), by = "-2min")
# sequence (date-time) of length 10 from now down by 10 seconds
seq(nw, by = -10, length.out = 10)
# sequence (time of day) of length 10 from now down by 10 seconds
seq(as.time(nw), by = -10, length.out = 10)
# explicit call to seq.tind with conversion
seq.tind("2025-01", "2025-12")
## corner cases
# from 2025-12-30 23:00 till end of 2025, note that 2025-12-31 24:00
# (that is 2025-01-01 00:00) is excluded from the result as it is in the next year
seq(as.tind("2025-12-30 23:00", tz = "UTC"), "2025", by = "5h")
# from end of 2025 down to 2025-12-30 23:00, note that 2025-12-31 24:00
# (that is 2025-01-01 00:00) is excluded from the result as it is in the next year
seq(as.tind("2025"), as.tind("2025-12-30 23:00", tz = "UTC"), by = "-5h")
Set Operations on Time Intervals and Time Indices
Description
Time intervals can be thought of as subsets of time line (set of integers or real line, depending on index type). The following functions perform operations on these sets.
unique method for objects of tinterval class returns unique
representation as ordered sum of disjoint, non-adjacent intervals.
! (negation) operator for objects of tinterval class returns
set-theoretical complement of the argument.
intersect_t, union_t, setdiff_t return intersection,
union and (asymmetric) set difference. These three functions accept
both time intervals and time indices.
Behaviour of !, intersect_t, union_t, and setdiff_t
is consistent with behaviour of %in_t% operator.
Consistency is also assured under type conversions.
For time indices, intersect_t, union_t, setdiff_t
behave just like intersect, union, setdiff from base
(see sets) but preserve class attribute.
Usage
## S3 method for class 'tinterval'
unique(x, ...)
## S3 method for class 'tinterval'
!x
intersect_t(x, y)
union_t(x, y)
setdiff_t(x, y)
Arguments
x |
an object of |
... |
(ignored) further arguments passed to or from other methods. |
y |
an object of |
Details
For discrete time indices (represented as integers, i.e. years, quarters,
months, weeks, dates, arbitrary integer indices) time intervals represent
the following sets (ignoring empty, i.e. with a_i > b_i):
\bigcup_{i = 1}^n A_i = \bigcup_{i = 1}^n \{x: a_i \le x \le b_i\} = \bigcup_{i = 1}^n \{a_i, a_i + 1, \dots, b_i - 1, b_i\}.
unique returns the unique (canonical) representation of the set above:
\bigcup_{i = 1}^{n'} A'_i = \bigcup_{i = 1}^{n'} \{a'_i, a'_i + 1, \dots, b'_i - 1, b'_i\}
with a'_i \le b'_i < a'_{i + 1} - 1, i.e. as a sum of ordered, non-empty,
non-adjacent intervals.
For continuous time indices (representing point in time, i.e. date-time, time of day,
arbitrary numeric indices) time intervals represent the following sets
(ignoring empty, i.e. with a_i \ge b_i):
\bigcup_{i = 1}^n A_i = \bigcup_{i = 1}^n [a_i, b_i).
unique returns unique representation of the set above:
\bigcup_{i = 1}^{n'} A'_i = \bigcup_{i = 1}^{n'} [a'_i, b'_i)
with a'_i < b'_i < a'_{i + 1}, i.e. as a sum of ordered, non-empty,
non-adjacent intervals.
Complement of a single interval for integer indices
\{x: a \le x \le b\} = \{a, a + 1, \dots, b - 1, b\}
is:
\{x: x < a\} \cup \{x: x > b\} = \{x: x \le a - 1\} \cup \{x: x \ge b + 1\} = \{\dots, a - 2, a - 1\} \cup \{b + 1, b + 2, \dots\}.
Complement of a single interval for continuous indices
[a, b)
is:
(-\infty, a) \cup [b, \infty).
Complement of a sum of intervals is the intersection of complements.
Set operations always return results in the canonical representation.
Value
An object of tinterval or tind class representing result of the set
operation.
See Also
tinterval for an overview of time interval class,
match_t for matching time indices
Examples
(x <- tinterval("2025-03-15", "2025-03-20") + c(0, 4, 14))
# unique representation (non-overlapping intervals)
unique(x)
# complement
!x
# binary set operations
(y <- tinterval("2025-03-01", "2025-03-31"))
intersect_t(x, y)
union_t(x, y)
setdiff_t(x, y)
setdiff_t(y, x)
# different types of indices
(y <- tinterval("2025-W10", "2025-W11"))
intersect_t(x, y)
union_t(x, y)
setdiff_t(x, y)
setdiff_t(y, x)
# check
(y <- as.tinterval(y, type = "d"))
intersect_t(x, y)
union_t(x, y)
setdiff_t(x, y)
setdiff_t(y, x)
Get Time Unit
Description
t_unit method returns time unit of time difference object
as a character value, either in short form (most often single letter,
code used internally) or long form (name).
units method for tdiff objects is equivalent
to t_unit with x argument only.
Usage
t_unit(x, long = TRUE, valid = FALSE)
## S3 method for class 'tdiff'
t_unit(x, long = TRUE, valid = FALSE)
## S3 method for class 'difftime'
t_unit(x, long = TRUE, valid = FALSE)
## S3 method for class 'tdiff'
units(x)
Arguments
x |
an object of |
long |
a logical value, if |
valid |
a logical value, if |
Details
Time differences (for example differences between date-time indices) are internally represented as number of seconds. However, the returned time unit is automatically determined based on the resolution of the argument. If all time differences are full hours or full minutes, appropriate unit is returned, see Examples. For time differences that contain zeros and missing values only, returned unit is a second.
Value
A character value.
See Also
Examples
(x <- as.tdiff(1, "y"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "q"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "m"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "w"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "d"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "h"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "min"))
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(1, "s"))
t_unit(x)
t_unit(x, FALSE)
# automatic unit determination
(x <- as.tdiff(600, "s")) # ten minutes
t_unit(x)
t_unit(x, FALSE)
(x <- as.tdiff(7200, "s")) # two hours
t_unit(x)
t_unit(x, FALSE)
Time Differences
Description
Objects of tdiff class represent time differences and are similar
to difftime objects. tdiff objects are created
by subtracting two time indices (of types other than "i" and "n")
or via calls to as.tdiff method. An alternative way of constructing
tdiff objects is to call years, qrtrs, mnths,
weeks, days, hours, mins, and secs
convenience functions.
The following units (argument unit) are supported:
"y"("year","years")differences in years,
"q"("quarter","quarters")differences in quarters,
"m"("month","months")differences in months,
"w"("week","weeks")differences in weeks,
"d"("day","days")differences in days,
"h"("hour","hours")differences in hours,
"min"("mins","minute","minutes")differences in minutes,
"s"("secs","second","seconds")differences in seconds.
Standard methods for vectors and conversion from / to numeric and character vectors are implemented for this class.
Usage
is.tdiff(x)
as.tdiff(x, ...)
## S3 method for class 'numeric'
as.tdiff(x, unit, ...)
## S3 method for class 'character'
as.tdiff(x, ...)
## S3 method for class 'difftime'
as.tdiff(x, ...)
years(x)
qrtrs(x)
mnths(x)
weeks(x)
days(x)
hours(x)
mins(x)
secs(x)
## S3 method for class 'tdiff'
as.character(x, ...)
## S3 method for class 'tdiff'
format(x, ...)
## S3 method for class 'tdiff'
as.data.frame(x, ...)
## S3 method for class 'tdiff'
x[i]
## S3 replacement method for class 'tdiff'
x[i] <- value
## S3 method for class 'tdiff'
x[[i]]
## S3 replacement method for class 'tdiff'
x[[i]] <- value
## S3 method for class 'tdiff'
rep(x, ...)
## S3 method for class 'tdiff'
c(...)
## S3 method for class 'tdiff'
Math(x, ...)
## S3 method for class 'tdiff'
Summary(..., na.rm = FALSE)
## S3 method for class 'tdiff'
mean(x, na.rm = FALSE, ...)
## S3 method for class 'tdiff'
unique(x, ...)
## S3 method for class 'tdiff'
print(x, ...)
## S3 method for class 'tdiff'
summary(object, ...)
Arguments
x |
a numeric vector or any R object coercible to |
... |
further arguments passed to or from other methods. |
unit |
a character string, name of the time unit, see Details. |
i |
an integer vector of indices or a logical vector indicating selection. |
value |
replacement value. |
na.rm |
a logical value indicating whether missing values should be removed. |
object |
an object of |
Details
tdiff objects are implemented as vectors of integers (for differences
in years, quarters, months, weeks, and days) or vectors of doubles (for time
differences). Time differences are internally represented in seconds
but when printing the actual time unit (hour, minute, second) is automatically
inferred and used.
Valid ranges for tdiff values depend on unit. These are defined
by differences of the maximal and minimal valid time indices of the type
corresponding to the time unit.
Value
as.tdiff as well as convenience functions years,
qrtrs, etc., return objects of tdiff class.
is.tdiff returns a logical value.
In general, methods for tdiff return objects of tdiff class.
as.character and format return character vectors.
as.data.frame returns a data frame with a single
column and the number of rows equal to the length of the argument.
print returns its argument invisibly and is used for its side effect.
summary returns an object of class c("summaryDefault", "table").
Note
Since as.difftime is not implemented in base as an S3 generic,
conversion from tdiff to difftime is not provided.
See Also
Ops for operations on time indices and time differences.
Examples
# how many days have passed since Jan 1, 2000?
today() - as.date("2000-01-01")
# how many months have passed since Sep 2008?
as.month(today()) - as.month("2008-09")
# create time differences in quarters
as.tdiff(-2:2, "q")
# same
(x <- qrtrs(-2:2))
# add to today
today() + x
Get Time Index Type
Description
ti_type method returns time index type as a character value, either
in short form (single letter, code used internally) or long form (name).
is.instant returns TRUE for continuous time indices representing
points in time (date-time, time of day, and numeric indices) and FALSE
for time discrete indices that represent periods of time, for example, days representing
(usually) 24 hours, weeks, months, quarter, and years (as well as integer indices).
Usage
ti_type(x, long = TRUE, valid = FALSE)
## S3 method for class 'tind'
ti_type(x, long = TRUE, valid = FALSE)
## S3 method for class 'Date'
ti_type(x, long = TRUE, valid = FALSE)
## S3 method for class 'POSIXt'
ti_type(x, long = TRUE, valid = FALSE)
is.instant(x)
Arguments
x |
an object of |
long |
a logical value, if |
valid |
a logical value, if |
Value
A character value for ti_type, a logical value
for is.instant.
Note
Behaviour of is.instant differs from that of identically named
function in lubridate package, which returns TRUE for all time
classes including dates.
See Also
Examples
ti_type(as.tind(1999))
ti_type(as.tind(1999), FALSE)
ti_type(as.tind("2001q3"))
ti_type(as.tind("2001q3"), FALSE)
ti_type(as.tind("2003-11"))
ti_type(as.tind("2003-11"), FALSE)
ti_type(as.tind("2004-W53"))
ti_type(as.tind("2004-W53"), FALSE)
ti_type(as.tind("2020-02-29"))
ti_type(as.tind("2020-02-29"), FALSE)
ti_type(today())
ti_type(today(), FALSE)
is.instant(today())
ti_type(now())
ti_type(now(), FALSE)
is.instant(now())
ti_type(Sys.Date())
ti_type(Sys.Date(), FALSE)
is.instant(Sys.Date())
ti_type(Sys.time())
ti_type(Sys.time(), FALSE)
is.instant(Sys.time())
Time Index Components (Years, Months, Days, ...)
Description
The following functions can be used to retrieve components of time indices.
year, quarter, month, week, day return
year (0–9999), quarter (1–4), month (1–12), week (1–53, ISO 8601),
and day (1–31) indices as integers. When month is invoked
with labels argument set to TRUE, an ordered factor is returned.
day_of_week returns index (1–7) of weekday with Monday as the first
day (as in ISO 8601). When invoked with labels argument
set to TRUE, an ordered factor is returned.
day_of_year returns index (1–366) of the day of year as integer.
hour, minute, second return hour (0–23),
minute (0–59), and second (0–59,999999) indices as integers and reals (for seconds).
am and pm functions determine whether time falls in the first
or second half of the day.
Methods weekdays, months, and quarters from package base
are implemented but users are encouraged to use functions from tind package.
Usage
year(x)
quarter(x)
## S3 method for class 'tind'
quarters(x, abbreviate)
month(x, labels = FALSE, abbreviate = TRUE, locale = NULL)
## S3 method for class 'tind'
months(x, abbreviate = FALSE)
week(x)
day(x)
day_of_year(x)
day_of_week(x, labels = FALSE, abbreviate = TRUE, locale = NULL)
## S3 method for class 'tind'
weekdays(x, abbreviate = FALSE)
hour(x)
am(x)
pm(x)
minute(x)
second(x)
Arguments
x |
an object of |
abbreviate |
a logical value, if |
labels |
a logical value, if |
locale |
(optional) a character value determining locale or |
Details
year for week arguments need not necessarily return the same value
as for days within the week in question when the week is the first or the last
in a year.
tind package does not provide replacement methods for time index components.
In order to change, say, month one can use tind constructor or %+m%
operator (and similar operators), see Examples.
Value
All functions return integer vectors, except for second, which
returns numeric vectors. Additionally, month and day_of_week
return ordered factors if invoked with argument labels set to TRUE.
See Also
tind class, Ops
for index increments / decrements and index differences, and
calendar-names for names of months and days of weeks in the current
locale. Further examples of use of these functions can be found
in calendar documentation.
Examples
# current date and time
(nw <- now())
# show current year, quarter, month, ...
year(nw)
quarter(nw)
month(nw)
month(nw, labels = TRUE)
month(nw, labels = TRUE, abbreviate = FALSE)
week(nw)
day(nw)
day_of_week(nw)
day_of_week(nw, labels = TRUE)
day_of_week(nw, labels = TRUE, abbreviate = FALSE)
day_of_year(nw)
hour(nw)
minute(nw)
second(nw)
# alternatives to replacement, change month to December
(x <- as.date("2023-09-11"))
(x <- tind(y = year(x), m = 12, d = day(x)))
(x <- as.date("2023-09-11"))
(x <- x %+m% (12 - month(x)))
Time Index Properties (Leap Years, Period Lengths, DST)
Description
The following functions can be used to determine whether years are leap years, compute the number of subperiods within a period, and determine whether Daylight Saving Time is on for particular date-time index. All function are vectorised.
is.leap_year returns TRUE for leap years and FALSE for
non-leap ones.
days_in_year and weeks_in_year return the number of days
(365–366) and the number of weeks (52–53) in a year.
days_in_quarter and days_in_month return the number of days
in a quarter (90–92) or a month (28–31), respectively.
hours_in_day returns the number of hours in a day (24 most
of the time, a different number during DST/UTC offset changes).
is.dst returns TRUE when Daylight Saving Time is on
and FALSE otherwise.
Usage
is.leap_year(x)
days_in_year(x)
weeks_in_year(x)
days_in_quarter(x)
days_in_month(x)
hours_in_day(x, tz = NULL)
is.dst(x)
Arguments
x |
an object of |
tz |
(optional) a character value determining the time zone (the default
|
Value
is.leap_year and is.dst return logical vectors.
The remaining functions return integer vectors, except for hours_in_day,
which returns numeric vectors.
See Also
time-index-components, calendrical-computations,
Ops, tzone, bizdays_in_month.
A Common Representation of Time Indices of Different Types
Description
tind is an S3 class representing time indices of different
types (years, quarters, months, ISO 8601 weeks, dates, date-time,
and arbitrary integer/numeric indices). Time indices are represented
by vectors of integers or doubles with type attribute and
time zone attribute (date-time only). Objects of tind behave like plain
vectors and can be easily used in data frames.
A tind object would usually be created using as.tind
method or using parse_t and strptind functions.
tind constructor allows to create time indices from components
(like year, month, day) and to create vectors of a given length
filled with NA values.
is.tind function checks whether an object is of tind class.
Usage
tind(..., length = 0L, type = NULL, tz = NULL)
is.tind(x)
Arguments
... |
components of time index to be constructed (in arbitrary order), the following are accepted:
|
length |
an integer value specifying the desired length. |
type |
a character value determining time index type
( |
tz |
(optional) a character value determining the time zone (the default
|
x |
any R object. |
Details
tind class supports the following types of time indices:
- years
internal code
"y".- quarters
internal code
"q".- months
internal code
"m".- weeks
internal code
"w".- dates
internal code
"d".- date-time
internal code
"t".- time of day
internal code
"h".- arbitrary integer index
"i".- arbitrary numeric index
"n".
Valid ranges for time indices are:
- years (
"y") 0000–9999.- quarters (
"q") 0000q1–9999q4.- months (
"m") 0000-01–9999-12.- weeks (
"w") 0000-W01–9999-W52.- dates (
"d") 0000-01-01–9999-12-31.- date-time (
"t") from
0000-01-01 15:00:00Zto9999-12-31 09:00:00Z(between-62167165200and253402246800seconds since the Unix epoch).- time of day (
"h") from
00:00to24:00(between0and86400seconds since midnight).
Value
An object of tind class for tind or a logical
value for is.tind.
See Also
as.tind for conversion to tind,
parse_t and strptind functions for
parsing character strings, date_time for construction
of date-time indices from date and time components, tind-methods
for basic methods.
Examples
# years
tind(y = 2010:2020)
tind(type = "y")
tind(length = 11, type = "y")
# quarters
tind(y = rep(2020:2023, each = 4), q = 1:4)
tind(q = 1:4, y = rep(2020:2023, each = 4))
tind(type = "q")
tind(length = 4, type = "q")
# months
tind(y = 2023, m = 1:12)
tind(m = 1:12, y = 2023)
tind(type = "m")
tind(length = 12, type = "m")
# weeks
tind(y = 2024, w = 1 + 2 * (0:25))
tind(type = "w")
tind(length = 13, type = "w")
# dates
tind(m = 3, d = 15, y = 2024)
tind(y = 2024, m = rep(1:3, each = 2), d = c(1, 15))
tind(type = "d")
tind(length = 6, type = "d")
# time of day
tind(H = 16, M = (0:3) * 15)
tind(type = "h")
tind(length = 4, type = "h")
# date-time
# system time zone
tind(y = 2024, m = 8, d = 2, H = 16, M = (0:3) * 15)
tind(y = 2024, m = 8, d = 2, H = 16, M = (0:3) * 15)
tind(y = 2024, m = 8, d = 2, H = 16, M = 0, S = 10 * (0:5))
# time zone explicitly provided
tind(y = 2024, m = 8, d = 2, H = 16, M = (0:3) * 15, tz = "UTC")
tind(type = "t")
tind(type = "t", tz = "UTC")
tind(length = 4, type = "t")
tind(length = 4, type = "t", tz = "UTC")
# integer and numeric indices
# (cannot be constructed from components like above)
tind(length = 10, type = "i")
tind(length = 10, type = "n")
Conversion of Objects of tind Class
Description
Objects of tind class can be easily converted to built-in R classes
inluding numeric, integer, character, Date,
POSIXct, POSIXlt, and data.frame.
Usage
## S3 method for class 'tind'
as.integer(x, ...)
## S3 method for class 'tind'
as.double(x, ...)
## S3 method for class 'tind'
as.character(x, ...)
## S3 method for class 'tind'
as.Date(x, ...)
## S3 method for class 'tind'
as.POSIXct(x, tz = NULL, ...)
## S3 method for class 'tind'
as.POSIXlt(x, tz = NULL, ...)
## S3 method for class 'tind'
as.data.frame(x, ...)
Arguments
x |
an object of |
... |
further arguments passed to or from other methods. |
tz |
(optional) a character value determining the time zone (the default
|
Details
as.double and as.numeric return internal representation
for particular time index type (seconds, days, weeks etc. since ...).
For years, quarters, months, weeks, and dates, as.integer returns
representation in the form YYYY, YYYYQ, YYYYMM, YYYYWW,
and YYYYMMDD, respectively. For other index types, as.integer
returns internal representation of time indices converted to integer.
as.character returns character vector with standard (ISO 8601)
representation of time indices. For customisable output formats,
see format.
as.Date, as.POSIXct, and as.POSIXlt return objects
of classes Date, POSIXct, and POSIXlt, respectively.
as.data.frame returns a 1-column data frame with time indices and
allows to work with time indices in data frames.
Value
as.xxx returns an object of xxx class of the same
length as the argument. as.data.frame returns a data frame with a single
column and the number of rows equal to the length of the argument.
See Also
format for customisable character output formats,
as.tind for conversion to tind.
For conversions between tind class and other classes (from packages
other than base), see tind-other.
Basic Methods for tind Class
Description
tind class supports all standard methods for vectors and
and vector-based classes like Date or POSIXct.
Usage
## S3 method for class 'tind'
x[i]
## S3 replacement method for class 'tind'
x[i] <- value
## S3 method for class 'tind'
x[[i]]
## S3 replacement method for class 'tind'
x[[i]] <- value
## S3 replacement method for class 'tind'
length(x) <- value
## S3 method for class 'tind'
rep(x, ...)
## S3 method for class 'tind'
c(...)
## S3 method for class 'tind'
unique(x, ...)
## S3 method for class 'tind'
print(x, ...)
## S3 method for class 'tind'
summary(object, ...)
Arguments
x |
an object of |
i |
an integer vector of indices or a logical vector indicating selection. |
value |
replacement value. |
... |
objects of |
object |
an object of |
Details
tind class supports standard indexing via [] and [[]]
operators, as well as replacement, In replacement, it is expected that the
right hand side is of the same type as the indexed object.
length, length<-, and rep methods work in a standard way.
rev, head, tail, as they are implemented using []
operator, are also available for objects of tind class.
Concatenation method (c) works in a standard way. It is expected that
all arguments are of the same type. Arguments that are not of tind class
are converted.
min, max, and range work in a standard way. If the results
are not proper time indices (for example maximum over a vector of length 0),
NAs are returned.
unique, duplicated, order, sort, etc.
work in a standard way.
print prints time indices on the console and invisibly returns its
argument.
summary method returns summary information about time indices.
Value
In general, methods return objects of tind class.
print returns its argument invisibly and is used for its side effect.
summary returns an object of class c("summaryDefault", "table").
See Also
format for formatting time indices,
Ops for operations on time indices.
Examples
# test sample
(dd <- as.tind(20210131) + sample((0:9), 15, replace = TRUE))
# indexing
dd[1]
dd[[1]]
dd[[1]] <- dd[[1]] + 1
dd
dd[2:3] <- dd[2:3] + 1
dd
# this will generate an error
try(
dd[10] <- now()
)
# length, length<-
length(dd)
length(dd) <- 7
dd
# rep, head, tail, rev
rep(dd, 2)
head(dd, 3)
tail(dd, -5)
rev(dd)
# min, max, range
min(dd)
max(dd)
range(dd)
# unique, duplicated
unique(dd)
duplicated(dd)
# order, sort
order(dd)
sort(dd)
# concatenation
c(dd, rev(dd))
# attempt at concatenating different types will result in an error
try(
c(today(), now())
)
Conversion between tind and Other Time Index Representations
Description
Besides Date, POSIXct, and POSIXlt classes from
package base, tind currently supports conversion between
tind and the following classes: yearmon, yearqtr
(both from package zoo), timeDate (from package timeDate),
chron, dates, times (from package chron),
and IDate, ITime (from package data.table).
Usage
## S3 method for class 'yearmon'
as.tind(x, ...)
as.yearmon(x, ...)
## S3 method for class 'yearqtr'
as.tind(x, ...)
as.yearqtr(x, ...)
## S3 method for class 'timeDate'
as.tind(x, digits = 0L, ...)
as.timeDate(x, ...)
## S3 method for class 'chron'
as.tind(x, digits = 0L, ...)
as.chron(x, ...)
## S3 method for class 'dates'
as.tind(x, ...)
as.dates(x, ...)
## S3 method for class 'times'
as.tind(x, digits = 0L, ...)
as.times(x)
## S3 method for class 'IDate'
as.tind(x, ...)
as.IDate(x, ...)
## S3 method for class 'ITime'
as.tind(x, ...)
as.ITime(x)
Arguments
x |
an R object to be converted. |
... |
(ignored) further arguments passed to or from other methods. |
digits |
an integer value (0–6) determining the number of decimal places for seconds to be preserved during conversion (0 by default). |
Details
Date-time indices resulting from conversion of chron objects
always have time zone set to UTC. Use tzone<-
or as.tzone methods when necessary.
Value
as.xxx returns an object of xxx class of the same
length as the argument.
See Also
as.tind and tind-coercion for conversions
to and from tind, date2num and num2date
for conversion between tind and integer representations of dates
(days since ...) found in different software packages.
Time Intervals
Description
Objects of auxiliary tinterval class represent time intervals as pairs
of time indices (start and end). Time intervals can be constructed via a call
to tinterval function or using convenience %--% operator.
Open-ended intervals are supported.
The main applications of this class are set operations (see set-ops)
and checking if a particular time index belongs to (one of) given interval(s)
(see match_t).
Usage
tinterval(start = NULL, end = NULL, ...)
start %--% end
is.tinterval(x)
as.tinterval(x, ...)
## S3 method for class 'character'
as.tinterval(x, sep, ...)
## S3 method for class 'tinterval'
as.tinterval(x, type = NULL, tz = NULL, ...)
## S3 method for class 'list'
as.tinterval(x, ...)
## S3 method for class 'data.frame'
as.tinterval(x, ...)
## S3 method for class 'tinterval'
as.character(x, ...)
## S3 method for class 'tinterval'
format(x, sep = " -- ", open = "...", aux = TRUE, empty = "-", ...)
## S3 method for class 'tinterval'
as.list(x, ...)
## S3 method for class 'tinterval'
as.data.frame(x, ...)
## S3 method for class 'tinterval'
x[i]
## S3 method for class 'tinterval'
x[[i]]
## S3 replacement method for class 'tinterval'
x[i] <- value
## S3 replacement method for class 'tinterval'
x[[i]] <- value
## S3 method for class 'tinterval'
c(...)
## S3 method for class 'tinterval'
print(x, ...)
## S3 method for class 'tinterval'
summary(object, ...)
Arguments
start |
an object of |
end |
an object of |
... |
objects of |
x |
an object of |
sep |
a character string used as separator between start and end
of an interval ( |
type |
a character determining time index type or |
tz |
(optional) a character value determining the time zone (the default
|
open |
a character string used to print open interval ends
( |
aux |
a logical value, if |
empty |
a character string used to mark empty intervals ( |
i |
an integer vector of indices or a logical vector indicating selection. |
value |
replacement value, should be coercible to |
object |
an object of |
Details
tinterval constructor takes two arguments: beginnings and ends of intervals.
Additional arguments (passed via ...) are forwarded to as.tind
method. x %--% y is equivalent to tinterval(x, y).
as.tinterval can be used to construct time intervals from character
strings, two-element lists, or two-column data frames. Additionally,
as.tinterval allows to convert time intervals represented using
one type of time indices to time intervals represented by time indices
of higher resolution (for example months to dates).
Internally, time intervals are represented by lists of two vectors. However, in operations they behave like vectors with standard indexing and replacement operators implemented.
Interval limits can be accessed via $ operator: x$start
returns vector of beginnings of intervals in x and x$end
vector of ends.
For discrete time indices (represented as integers, i.e. years, quarters,
months, weeks, dates, arbitrary integer indices) time interval a %--% b
represents all indices falling in a or after and in b or before, i.e.
the set: \{x: a \le x \wedge x \le b\} = \{a, a + 1, \dots, b - 1, b\}.
For continuous time indices (representing point in time, i.e. date-time, time of day,
arbitrary numeric indices) time interval a %--% b represents
all indices starting with a and before b, i.e. the set:
[a, b).
The difference in interpretations between discrete and continuous time indices
assures consistency during conversions.
Consider time interval "2025-08-02" %--% "2025-08-03". This represents
all date-time indices falling on one of those two days, so exactly 2025-08-02 00:00
or after but before 2025-08-04 00:00.
Value
tinterval, %--%, and as.tinterval return
objects of tinterval class.
is.tinterval returns a logical value.
In general, methods for tinterval return objects of tinterval class.
as.character and format return character vectors.
as.list and as.data.frame return a two-element list and
a two-column data frame, respectively. Names are set to c("start", "end").
print returns its argument invisibly and is used for its side effect.
summary returns an object of class c("summaryDefault", "table").
See Also
set-ops for the description of set operations on time intervals,
match_t for matching time indices to time intervals.
Examples
td <- today()
# from today till the day after tomorrow
td %--% (td + 2)
# from today till the end of next year
td %--% (as.year(td) + 1)
# from the beginning of the year till today
as.year(td) %--% td
# 9 to 5
as.time("9am") %--% as.time("5pm")
# 7 to 9 and 4 to 6 via constructor...
tinterval(as.time(c("7am", "4pm")), as.time(c("9am", "6pm")))
# ... or more naturally via concatenation
c(as.time("7am") %--% as.time("9am"), as.time("4pm") %--% as.time("6pm"))
# automatic parsing
as.tinterval(c("2023-01 -- 2024-06", "2024-12 -- 2025-03"))
# empty time interval
as.tinterval(c("2024-01 -- 2023-06"))
# open time interval
"2024-01" %--% NULL
"2024-01" %--% as.month(NA)
as.tinterval(c("2024-01 -- ..."))
# +/- operators
(x <- tinterval(td, td + 2))
x + c(0, 7, 14)
x %+w% 0:2
# indexing
(x <- "2023-01" %--% "2024-06")
(x <- x %+y% c(0, 2, 4))
x[2:3]
x[-1]
# beginnings and ends of intervals
x$start
x$end
# conversion from interval represented by months to dates
(x <- "2025-07" %--% "2025-08")
as.tinterval(x, "d")
# conversion from interval represented by dates to date-time (see Details)
(x <- "2025-08-02" %--% "2025-08-03")
as.tinterval(x, "t")
Determine Time Span of Time Indices and Time Intervals
Description
tspan method determines the time span of time indices and time intervals.
Usage
tspan(x, ...)
## Default S3 method:
tspan(x, ...)
## S3 method for class 'tind'
tspan(x, na.rm = FALSE, ...)
## S3 method for class 'tinterval'
tspan(x, ...)
Arguments
x |
an object of |
... |
further arguments passed to or from other methods. |
na.rm |
a logical value indicating whether missing values should be removed. |
Details
Given tind argument, tspan returns a single tdiff
(or a single number for types "i" and "n") giving time span
of indices.
tspan for tinterval argument returns a tdiff of the same
length as the argument giving spans of time intervals.
Time spans are determined differently for time indices representing
periods of time (for example days) and for time indices that represent points
in time as determined by is.instant function. A sequence
of 3 consecutive dates has span of 3 days and a sequence of 5 consecutive
integers has span 5. On the other hand, a sequence of 3 consecutive hours
will have span of 2 hours, the difference between the last and the first hour,
see Examples.
Value
A tdiff or a numeric vector (for integer and numeric indices).
See Also
tinterval class, is.instant function,
resolution_t method for determining the resolution of time indices,
is.regular method for checking if time indices form a regular
sequence.
Examples
# 4 consecutive days
(x <- today() + 0:3)
tspan(x)
# 10 consecutive integers
(x <- as.tind(1:10, "i"))
tspan(x)
# 4 consecutive hours
(x <- tind(H = 12:15))
# span is 3 hours (not 4)
tspan(x)
# the same
tind(H = 15) - tind(H = 12)
Read or Set Time Zone for Date-Time Indices
Description
Date-time indices (objects of tind class of type "t")
always have the time zone attribute set. The time zone setting affects
how time (measured relative to the Unix epoch in UTC) is translated to local
time. Objects of base POSIXct and POSIXlt classes also have
an optional time zone attribute. tzone method is also implemented for some
other classes supported by the tind package.
List of time zones supported by a particular R installation can be obtained
via a call to OlsonNames function, see Examples.
Usage
tzone(x)
tzone(x) <- value
## S3 method for class 'tind'
tzone(x)
## S3 replacement method for class 'tind'
tzone(x) <- value
## S3 method for class 'tinterval'
tzone(x)
## S3 replacement method for class 'tinterval'
tzone(x) <- value
## S3 method for class 'POSIXct'
tzone(x)
## S3 replacement method for class 'POSIXct'
tzone(x) <- value
## S3 method for class 'POSIXlt'
tzone(x)
## S3 replacement method for class 'POSIXlt'
tzone(x) <- value
Arguments
x |
an object of |
value |
a character value, the new time zone attribute. |
Details
If the provided name is not in the list of supported time zones, an attempt is made to identify it via approximate match. If the result is a single time zone, it is accepted with a warning.
Unambiguous city names are automatically recognised, see Examples.
An attempt to set time zone attribute of a time index
of different type than date-time ("t") will lead to an error.
In case of POSIXct/POSIXlt objects with no time zone attribute,
the extractor returns the system time zone.
Value
For the extractor, the time zone as a character value (or NULL
for classes without time zone attribute). For the replacement, the argument
with the modified time zone.
See Also
Examples
# check time in the system time zone
(nw <- now())
# get time zone
tzone(nw)
# set time zone to UTC
tzone(nw) <- "UTC"
nw
tzone(nw)
# check time in different time zones
if ("Asia/Tokyo" %in% OlsonNames()) {
tzone(nw) <- "Asia/Tokyo"
nw
}
if ("Europe/Warsaw" %in% OlsonNames()) {
tzone(nw) <- "Europe/Warsaw"
nw
}
if ("America/New_York" %in% OlsonNames()) {
tzone(nw) <- "America/New_York"
nw
}
# try invalid time zone => error
try(
tzone(nw) <- "Hasdfg/Qwerty"
)
# unambiguous city names are automatically recognised
tzone(nw) <- "Tokyo"
nw
tzone(nw) <- "Warsaw"
nw
tzone(nw) <- "New York"
nw
# incomplete names and approximate matches are also recognised with a warning
if ("Europe/Warsaw" %in% OlsonNames()) try({
tzone(nw) <- "Warsa"
nw
})
if ("America/New_York" %in% OlsonNames()) try({
tzone(nw) <- "NewYork"
nw
})
# list first 6 supported time zones using base::OlsonNames
head(OlsonNames())
# list first 6 supported time zones with string "Europe"
head(grep("Europe", OlsonNames(), value = TRUE))
# list first 6 supported time zones with string "Asia"
head(grep("Asia", OlsonNames(), value = TRUE))
# list first 6 supported time zones with string "Africa"
head(grep("Africa", OlsonNames(), value = TRUE))
# list first 6 supported time zones with string "America"
head(grep("America", OlsonNames(), value = TRUE))
Converting Time Indices to Year Fractions and Back
Description
year_frac computes year fraction corresponding to a time index.
yf2tind performs the reverse computation.
Usage
year_frac(x)
yf2tind(x, type = NULL, tz = NULL)
Arguments
x |
an object of |
type |
a character value determining time index type
( |
tz |
(optional) a character value determining the time zone (the default
|
Details
year_fraction returns numeric vector representing time indices
in the form year + year fraction. For years this is equivalent to
as.numeric. Year fraction is determined based on the index
within particular year (minus 1 for all indices except for date-time)
and the number of periods within the year.
E.g., 2001Q1 gives 2001 (2001 + (1 - 1) / 4),
2001Q3 — 2001.5 (2001 + (3 - 1) / 4),
2010-04 (April 2010) — 2010.25 (2010 + (4 - 1) / 12),
2000-02-29 (60th day in 2000) — 2000.1612
(2000 + (60 - 1) / 366, 2000 was a leap year).
Value
A numeric vector for year_frac and tind for yf2tind.
Result is of the same length as argument.
Note
year_frac is not to be confused with a similarly called function
(YEARFRAC) found in popular spreadsheet software. In order to compute
differences between dates as year fractions use daycount_frac
function.
See Also
Examples
year_frac(today())
year_frac(now())
yf2tind(2023.5, "y")
yf2tind(2023.5, "q")
yf2tind(2023.5, "m")
yf2tind(2023.5, "w")
yf2tind(2023.5, "d")
yf2tind(2023.5, "t")