Time Axes¶
Dataface auto-detects the chronological grain of date columns and renders bucketed-time axes as ordinal (evenly-spaced category bands) by default. Bar, line, and area charts all follow the same rule: the band scale gives bars their full width, aligns line dots with bar centers, and keeps data-table column spacing uniform — without any per-chart-type patches.
You can override the detected grain, use explicit time-part units, disable bucketing entirely, or opt back into a continuous temporal scale for the rare cases that need it.
For how time-axis labels themselves are laid out (when they tilt, when they drop, when a continuous time axis bar chart stays vertical even when crowded), see Axis Labels — Smart Layout.
Auto-detection¶
When x is a date/datetime column on a bar, line, or area chart,
Dataface inspects the distinct values and picks a grain via two coexisting
detection paths: calendar-date predicates (for ISO date/datetime values) and
labeled string patterns (for period key strings). Both paths produce a VL
timeUnit; the column must use one path exclusively — mixed shapes error.
Calendar-date predicate path¶
| Detected grain | Predicate |
|---|---|
year |
All distinct values fall on January 1 |
yearquarter |
All fall on the 1st of Jan / Apr / Jul / Oct |
yearmonth |
All fall on the 1st of any month |
yearweek |
All fall on a Monday (ISO week-start) |
yearmonthdate |
All values are at midnight (daily) |
| (none — continuous) | Any value has nonzero hours/minutes/seconds |
Labeled period-key path¶
Warehouse exports often return period keys as strings rather than dates. Dataface recognizes these stable shapes directly:
| Pattern | Example | Detected grain |
|---|---|---|
YYYY-Www (ISO week-year) |
2024-W32 |
yearweek |
W[eek ]N YYYY |
W32 2024, Week 32 2024 |
yearweek |
YYYY-Qn (canonical quarter) |
2024-Q3 |
yearquarter |
Qn YYYY |
Q3 2024 |
yearquarter |
YYYYQn |
2024Q3 |
yearquarter |
YYYY-MM |
2024-01 |
yearmonth |
Mon YYYY (English month) |
Jan 2024 |
yearmonth |
MM/YYYY (US month/year) |
01/2024 |
yearmonth |
FYnnnn (fiscal year key) |
FY2024 |
year (mapped to Jan 1) |
MM/DD/YYYY (US month/day/year) |
01/15/2024 |
yearmonthdate |
Mon DD[,] YYYY |
Jan 15, 2024 |
yearmonthdate |
Scope: Calendar quarters only (Q1 = Jan–Mar, Q2 = Apr–Jun, Q3 = Jul–Sep,
Q4 = Oct–Dec). Fiscal-quarter offsets are not supported; set
style.axis_x.time_unit explicitly for non-calendar fiscal periods.
FY strings map to the year grain with Jan 1 as anchor — no fiscal calendar
offset is applied.
US-only formats: MM/YYYY and MM/DD/YYYY are parsed as US month/day order.
European day-first ambiguity is not detected; set time_unit explicitly if your
warehouse returns day-first slash-delimited dates.
Not supported: H1 YYYY / YYYY-H1 half-year strings (no Vega-Lite
timeUnit for half-year buckets). These are treated as unparseable; use
time_unit: year explicitly.
Detection produces encoding.x.type: ordinal in the emitted VL spec (the
default since D-002). Each detected bucket becomes an evenly-spaced band on the
x-axis. Bar width, line-dot alignment, and data-table column spacing all follow
band geometry automatically.
Authoring¶
Override the detected grain or disable bucketing via style.axis_x.time_unit:
charts: - id: monthly_revenue type: bar x: month y: revenue style: axis_x: time_unit: yearmonth # explicit override
Valid values:
| Value | Meaning |
|---|---|
auto |
Default — auto-detect from data |
year |
Force year bucketing |
yearquarter |
Force quarter bucketing |
yearmonth |
Force month bucketing |
yearweek |
Force ISO-week bucketing |
yearmonthdate |
Force daily bucketing |
monthofyear |
Extract month-of-year (Jan ... Dec) |
dayofweek |
Extract day-of-week |
dayofmonth |
Extract day-of-month |
dayofyear |
Extract day-of-year |
hourofday |
Extract hour-of-day |
none |
Disable bucketing — continuous temporal scale |
Dataface uses long-form names for time-part units, then maps them to Vega-Lite
primitives at emission time: monthofyear -> month, dayofweek -> day,
dayofmonth -> date, dayofyear -> dayofyear, and hourofday -> hours.
Scale type: ordinal (default) vs temporal (escape hatch)¶
Bucketed-time axes default to ordinal. To opt into a continuous temporal scale
— for irregular sampling where visual gaps must be preserved — set axis_x.type:
style: axis_x: type: temporal # escape hatch: continuous time scale
axis_x.type |
Scale | When to use |
|---|---|---|
auto (default) |
Ordinal for all bucketed grains | The common case: regular calendar cadence |
ordinal |
Ordinal (explicit) | Same as auto; useful to document intent |
temporal |
Continuous temporal | Irregular sampling; visual gaps required |
time_unit: none always produces a continuous temporal scale regardless of
axis_x.type.
Supported source formats per grain¶
year¶
| Source format | Example |
|---|---|
| ISO date at Jan 1 | 2024-01-01 |
Python date object |
date(2024, 1, 1) |
| Fiscal-year key | FY2024 (mapped to Jan 1) |
Recommended SQL: date_trunc('year', date) AS year (produces ISO dates for
auto-detection). EXTRACT(YEAR FROM date) returns an integer column which is
typed quantitative, not temporal.
yearquarter¶
| Source format | Example |
|---|---|
| ISO date at quarter start | 2024-01-01, 2024-04-01, 2024-07-01, 2024-10-01 |
| Canonical quarter label | 2024-Q1, 2024-Q2, 2024-Q3, 2024-Q4 |
| Quarter-first label | Q1 2024, Q2 2024 |
| Compact quarter label | 2024Q1, 2024Q2 |
Recommended SQL: date_trunc('quarter', date) AS quarter (produces ISO
dates), or CONCAT(YEAR, '-Q', QUARTER) AS quarter for labeled exports.
yearmonth¶
| Source format | Example |
|---|---|
| ISO date at month start | 2024-01-01, 2024-02-01, … |
Python date at month start |
date(2024, 1, 1) |
| Year-month string | 2024-01, 2024-12 |
| English month-name string | Jan 2024, February 2024 (3-letter abbreviation only) |
| US month/year slash | 01/2024, 12/2024 |
Recommended SQL: date_trunc('month', date) AS month
Display: Smart default applies %b %Y → Jan 2024 on the ordinal axis via
axis.formatType: "time". Override with style.axis_x.format.
yearweek¶
| Source format | Example |
|---|---|
| ISO date at week start (Monday) | 2024-01-01, 2024-01-08, … |
| ISO week-year label | 2024-W01, 2024-W32 |
| Spelled week label | W32 2024, Week 32 2024 |
Recommended SQL: date_trunc('week', date) AS week (produces ISO dates), or
CONCAT(ISO_YEAR, '-W', LPAD(ISO_WEEK, 2, '0')) AS week for labeled exports.
Note: ISO week-start is Monday. US Sunday-start weeks are out of scope.
Default label cadence: Monthly (Jan, Feb, …) — shows month openers so
dense weekly axes remain readable. Set label.time_unit: yearweek to restore
per-week labels.
yearmonthdate (daily)¶
| Source format | Example |
|---|---|
| ISO date | 2024-01-15 |
| ISO datetime at midnight | 2024-01-15T00:00:00 |
Python date / datetime (midnight) |
date(2024, 1, 15) |
| US month/day/year slash | 01/15/2024 |
| English day-name string | Jan 15, 2024, Jan 15 2024 |
Recommended SQL: date::DATE or date_trunc('day', date)
Time-Part Units¶
Use time-part units when the question compares a recurring calendar part rather than elapsed time. The x column should still be a real date or timestamp; Vega- Lite extracts the requested part. Time-part units remain on a temporal scale (they represent cyclic comparison, not ordered buckets).
charts: - id: revenue_by_month_of_year type: bar x: order_date y: revenue style: axis_x: time_unit: monthofyear format: "%b" - id: orders_by_day_of_week type: bar x: order_ts y: order_count style: axis_x: time_unit: dayofweek format: "%a"
time_unit: auto does not infer time-part intent from field names. If you want
seasonality, day-of-week, or hour-of-day behavior, author the time part
explicitly.
Failures¶
Dataface fails loud (raises an error) when:
- ≥10% of distinct values are unparseable as dates or recognized label patterns. Fix the query or cast the column.
- A column contains mixed shapes — e.g. some values are
2024-W32(week labels) and others are2024-01-15(ISO dates), or week labels alongside quarter labels. Setstyle.axis_x.time_unitexplicitly for ambiguous columns.
Use style.axis_x.time_unit: none for raw event data with sub-daily
timestamps — detection returns continuous temporal automatically, but the
explicit override documents intent.
Axis labels¶
style.axis_x.time_unit controls the data bucket sent to Vega-Lite. Use
style.axis_x.label.time_unit only when the label cadence should differ from
the encoded bucket.
style: axis_x: time_unit: yearmonth label: time_unit: yearquarter
When label.time_unit is omitted, it inherits the axis time unit except
yearweek, which defaults to yearmonth labels so weekly charts read as
Jan/Feb/Mar rather than W01/W02/W03. Set label.time_unit: yearweek explicitly
to restore week labels. Set label.time_unit: none to disable Dataface's smart
label expression and let Vega-Lite format the axis.
For simple formatting, use style.axis_x.format:
style: axis_x: time_unit: yearmonth format: "%b %Y"