Skip to content

How to Add Calendar and Time Features

This guide shows you how to derive calendar, holiday, Fourier, and trend features from the time column and pass them to a forecaster as deterministic inputs.

Prerequisites

Try it interactively

How to Add Calendar, Fourier, and Holiday Features

Enrich your feature matrix with time-derived signals using CalendarFeatureTransformer, FourierFeatureTransformer, and HolidayFeatureTransformer.

ViewOpen in marimo

Extract Calendar Features

CalendarFeatureTransformer extracts integer features from timestamps. Pass a list of feature names, or leave features=None to auto-detect all features applicable to your data's frequency:

from yohou.preprocessing import CalendarFeatureTransformer
from yohou.datasets import fetch_electricity_demand

data = fetch_electricity_demand()
y = data.frame

transformer = CalendarFeatureTransformer(features=["month", "day_of_week", "hour"])
X = transformer.fit_transform(y)
# Output columns: cal_month, cal_day_of_week, cal_hour

Available features include "year", "month", "quarter", "week", "day_of_week", "day_of_month", "day_of_year", "hour", "minute", and boolean indicators like "is_weekend", "is_month_start", "is_month_end", "is_quarter_start", "is_quarter_end", "is_year_start", "is_year_end".

Frequency aware

Sub-daily features ("hour", "minute") are only applicable to sub-daily data. When features=None, the transformer inspects the data interval and extracts only what makes sense. After fitting, check transformer.applicable_features_ to see which features were selected.

Mark Holidays

HolidayFeatureTransformer creates a binary indicator column and optional proximity features showing distance to the nearest holiday:

from yohou.preprocessing import HolidayFeatureTransformer
import polars as pl
from datetime import date

holidays = pl.DataFrame({
    "date": [date(2024, 1, 1), date(2024, 7, 4), date(2024, 12, 25)]
})

transformer = HolidayFeatureTransformer(
    holidays=holidays,
    days_to_next=True,
    days_since_last=True,
)
X = transformer.fit_transform(y)
# Output columns: holiday_indicator, holiday_days_to_next, holiday_days_since_last

The holidays DataFrame needs a "date" column of Date or Datetime type. Set days_to_next=True or days_since_last=True to add integer columns measuring the distance (in days) to surrounding holidays.

Add Fourier Features

FourierFeatureTransformer captures smooth seasonal patterns with sine/cosine pairs at specified harmonics:

from yohou.preprocessing import FourierFeatureTransformer

transformer = FourierFeatureTransformer(seasonality=24, harmonics=[1, 2, 3])
X = transformer.fit_transform(y)
# Output columns: fourier_24_sin_1, fourier_24_cos_1, fourier_24_sin_2, ...

Set seasonality to the period length in time steps (e.g., 24 for daily cycles in hourly data, 365.25 for yearly cycles in daily data). Use more harmonics for sharper seasonal shapes, fewer for smoother patterns. Harmonics must satisfy the Nyquist limit: each harmonic \(k\) must be at most \(S/2\) where \(S\) is the seasonality.

Create a Trend Index

TimeIndexTransformer converts timestamps to a numeric index, useful for capturing linear or polynomial trends:

from yohou.preprocessing import TimeIndexTransformer

transformer = TimeIndexTransformer(normalize=True, degree=2)
X = transformer.fit_transform(y)
# Output columns: time_index, time_index_2

With degree=1 (the default), the transformer produces a single time_index column. Higher degrees add polynomial terms (time_index_2, time_index_3, etc.). Set normalize=True to scale the index to [0, 1] based on the training data length, which improves numerical stability for polynomial features.

Combine Multiple Time Features

Use FeatureUnion to run multiple time feature transformers in parallel and concatenate their outputs, then pass the result as feature_transformer to any forecaster:

from yohou.compose import FeatureUnion
from yohou.preprocessing import (
    CalendarFeatureTransformer,
    FourierFeatureTransformer,
    TimeIndexTransformer,
)
from yohou.point import PointReductionForecaster
from sklearn.linear_model import Ridge

features = FeatureUnion([
    ("calendar", CalendarFeatureTransformer(features=["month", "day_of_week", "hour"])),
    ("fourier", FourierFeatureTransformer(seasonality=24, harmonics=[1, 2, 3])),
    ("trend", TimeIndexTransformer(normalize=True)),
])

forecaster = PointReductionForecaster(
    estimator=Ridge(),
    feature_transformer=features,
)
forecaster.fit(y, forecasting_horizon=24)
predictions = forecaster.predict()

For more complex compositions (sequential chaining, nesting), see How to Compose Feature Pipelines.

feature_transformer vs X_future

When time features are passed via feature_transformer, the forecaster generates them automatically at both fit and predict time. If you generate calendar or Fourier features externally (outside feature_transformer), pass them via X_future at both fit() and predict() time, since they are deterministic and known in advance. See Exogenous Features for details.

See Also