Skip to content

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 %YJan 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 are 2024-01-15 (ISO dates), or week labels alongside quarter labels. Set style.axis_x.time_unit explicitly 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"