Skip to contents

mixtime provides flexible time classes for time series analysis and forecasting with mixed temporal granularities. It is designed for handling temporal data at different frequencies, making it ideal for:

  • Changing observation frequencies (e.g., historical quarterly records now reported monthly)
  • Analysis involving data at different temporal resolutions (e.g., quarterly tourism and monthly turnover)
  • Forecasting with temporal reconciliation across multiple time scales

Key Features

📈 Linear Time - Create linear time vectors with linear_time() or with helpers:

🔄 Cyclical Time - Create cyclical time vectors with cyclical_time() or with helpers:

⏳ Time durations - Create time duration vectors with duration() or with helpers:

🕰️ Time types

  • Discrete and continuous time models
  • Timezone support for all chronons
  • Custom granule sizes (e.g. week(2L) for fortnights)
  • Mixed granularity vectors for different temporal resolution over time (or series)

📅 Calendar Systems - Support for several calendars:

  • cal_gregorian - Gregorian dates (e.g. 2026-02-17)
  • cal_isoweek - ISO week dates (e.g. 2026-W8-Tue)
  • cal_sym454 - Symmetry454 dates (e.g. 2026-Feb-W4-Tue)
  • More calendars coming, including custom censored calendars

🧮 Temporal Operations

Installation

The mixtime package can be installed from CRAN with:

install.packages("mixtime")

The development version can be installed from GitHub with:

# install.packages("remotes")
remotes::install_github("mitchelloharawild/mixtime")

Usage

library(mixtime)
#> 
#> Attaching package: 'mixtime'
#> The following objects are masked from 'package:base':
#> 
#>     date, months, quarters
demo_time <- as.POSIXct("2026-02-22 18:30:42", tz = "UTC")
demo_date <- as.Date("2026-02-22")

The mixtime package is designed around the time units of calendars. These time units are used to create and manipulate time vectors.

Calendars and time units

Calendars have a cal_* prefix, which contain a set of time units that can be accessed with <cal>$<unit>. Using time units as functions produces time granules.

# The Gregorian calendar
cal_gregorian
#> <cal_gregorian>
#> Time units:
#>   - year
#>   - quarter
#>   - month
#>   - day
#>   - ampm
#>   - hour
#>   - minute
#>   - second
#>   - millisecond

# A 1-month time granule
cal_gregorian$month(1L) # (1L is integer 1)
#> <mixtime::tu_month>
#>  @ n : int 1
#>  @ tz: chr ""

# A 2-week time granule (fortnights)
cal_isoweek$week(2L)
#> <mixtime::tu_week>
#>  @ n : int 2
#>  @ tz: chr ""

Linear Time

A linear time vector uses time granules to define the resolution of time points, known as a chronon (the smallest granules of time). When the input time has a different resolution than the chronon, it will be automatically converted.

linear_time(demo_date, chronon = cal_gregorian$month(1L))
#> <mixtime[1]>
#> [1] 2026 Feb

Discrete time models (integer-based values) are used by default, however continuous time models (double-based values) can be used with discrete = FALSE to allow fractional chronons.

# February 22nd is 75% through the month (in non-leap years)
linear_time(demo_date, chronon = cal_gregorian$month(1L), discrete = FALSE)
#> <mixtime[1]>
#> [1] 2026 Feb 75.0%

Linear time helper functions are available to quickly create common time points.

# Create time vectors at different granularities
yearquarter(demo_date) + 0:7
#> <mixtime[8]>
#> [1] 2026 Q1 2026 Q2 2026 Q3 2026 Q4 2027 Q1 2027 Q2 2027 Q3 2027 Q4
yearmonth(demo_date) + 0:11
#> <mixtime[12]>
#>  [1] 2026 Feb 2026 Mar 2026 Apr 2026 May 2026 Jun 2026 Jul 2026 Aug 2026 Sep
#>  [9] 2026 Oct 2026 Nov 2026 Dec 2027 Jan
yearweek(demo_date) + 0:10
#> <mixtime[11]>
#>  [1] 2026 W08 2026 W09 2026 W10 2026 W11 2026 W12 2026 W13 2026 W14 2026 W15
#>  [9] 2026 W16 2026 W17 2026 W18
date(demo_date) + 0:6
#> <mixtime[7]>
#> [1] 2026-02-22 2026-02-23 2026-02-24 2026-02-25 2026-02-26 2026-02-27 2026-02-28

The mixtime package allows time of different granulities to be combined in a single vector.

c(
  year(demo_date), yearquarter(demo_date), 
  yearmonth(demo_date), yearweek(demo_date)
)
#> <mixtime[4]>
#> [1] 2026     2026 Q1  2026 Feb 2026 W08

Cyclical Time

A cyclical time vector is defined by two time granules: a chronon (the smaller granule of time) and a cycle (the larger granule that the chronon loops over).

# The `calendar` argument provides a masking scope to `chronon` and `cycle`
cyclical_time(demo_date, chronon = day(1L), cycle = week(1L), calendar = cal_isoweek)
#> <mixtime[1]>
#> [1] Sun

There are several cyclical time helper functions for convenience.

# Extract cyclical components
month_of_year(demo_date)
#> <mixtime[1]>
#> [1] Feb
week_of_year(demo_date)
#> <mixtime[1]>
#> [1] W08
day_of_week(demo_date)
#> <mixtime[1]>
#> [1] Sun

# Continuous cyclical time shows progress through chronons
day_of_week(demo_time, discrete = FALSE)
#> <mixtime[1]>
#> [1] Sun 77.1%

Timezones

All linear and cyclical time vectors support timezones via the tz argument.

demo_time
#> [1] "2026-02-22 18:30:42 UTC"
# Same day (Sunday) in LA
date(demo_time, tz = "America/Los_Angeles")
#> <mixtime[1]>
#> [1] 2026-02-22 PST
date(demo_time, tz = "America/Los_Angeles", discrete = FALSE)
#> <mixtime[1]>
#> [1] 2026-02-22 PST 43.8%
day_of_week(demo_time, tz = "America/Los_Angeles")
#> <mixtime[1]>
#> [1] Sun PST

# Next day (Monday) in Melbourne (23% through the 23rd)
date(demo_time, tz = "Australia/Melbourne")
#> <mixtime[1]>
#> [1] 2026-02-23 AEDT
date(demo_time, tz = "Australia/Melbourne", discrete = FALSE)
#> <mixtime[1]>
#> [1] 2026-02-23 AEDT 23.0%
day_of_week(demo_time, tz = "Australia/Melbourne")
#> <mixtime[1]>
#> [1] Mon AEDT

Temporal Manipulation

Linear time points can be adjusted to the floor, ceiling, or rounded to a specified time granule.

# Round dates to different granularities
time_floor(demo_date, cal_gregorian$month(1L))
#> [1] "2026-02-01"
time_round(demo_date, cal_isoweek$week(1L))
#> [1] "2026-02-23"
time_ceiling(demo_date, cal_gregorian$month(1L))
#> [1] "2026-03-01"

Time Sequences

The seq() function creates sequences of time points iterating by a given time granule.

# Integer increments (advances by chronon's natural granule)
seq(yearmonth(demo_date), by = 1L, length.out = 10)
#> <mixtime[10]>
#>  [1] 2026 Feb 2026 Mar 2026 Apr 2026 May 2026 Jun 2026 Jul 2026 Aug 2026 Sep
#>  [9] 2026 Oct 2026 Nov

# Time can be sequenced by different granules than the chronon
seq(date(demo_date), by = cal_gregorian$month(1L), length.out = 8)
#> <mixtime[8]>
#> [1] 2026-02-22 2026-03-22 2026-04-22 2026-05-22 2026-06-22 2026-07-22 2026-08-22
#> [8] 2026-09-22