---
title: "Time Series"
enterprise: true
framework: javascript
version: "36.1.0"
---

# Time Series

This section covers how to chart time series data using Integrated Charts.

Integrated Charts supports the charting of time series data using line and area charts when a time axis is chosen instead of a category or numeric axis.

## Time vs Category Axis

A [Time Axis](https://www.ag-grid.com/charts/react/axes-types/#time) is used to plot continuous date / time values, whereas a [Category Axis](https://www.ag-grid.com/charts/react/axes-types/#category) is used to plot discrete values or categories.

The example below highlights the differences between time and category axes. Notice that the time axis contains all days for the range of values provided, whereas the category axis only shows axis labels for the discrete values provide.

#### Time vs Category Axis

```ts
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  ClientSideRowModelModule,
  ColDef,
  ColumnApiModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  ValueFormatterParams,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  IntegratedChartsModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { getData } from "./data";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ColumnApiModule,
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
]);

let gridApi: GridApi;
let currentChartRef: any;

function getColumnDefs() {
  return [
    { field: "date", valueFormatter: dateFormatter },
    { field: "avgTemp" },
  ];
}

const gridOptions: GridOptions = {
  columnDefs: getColumnDefs(),
  defaultColDef: { flex: 1 },
  cellSelection: true,
  popupParent: document.body,
  enableCharts: true,
  chartThemeOverrides: {
    line: {
      title: {
        enabled: true,
        text: "Average Daily Temperatures",
      },
      navigator: {
        enabled: true,
        height: 20,
        spacing: 25,
      },
      axes: {
        time: {
          label: {
            rotation: 0,
            format: "%d %b",
          },
        },
        category: {
          label: {
            rotation: 0,
            formatter: (params: any) => {
              // charts typings
              return formatDate(params.value);
            },
          },
        },
        number: {
          label: {
            formatter: (params: any) => {
              // charts typings
              return params.value + "°C";
            },
          },
        },
      },
    },
  },
  chartToolPanelsDef: {
    panels: ["data", "format"],
  },
  onGridReady: (params: GridReadyEvent) => {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  },
  onFirstDataRendered,
};

function onFirstDataRendered(params: FirstDataRenderedEvent) {
  if (currentChartRef) {
    currentChartRef.destroyChart();
  }

  currentChartRef = params.api.createRangeChart({
    chartContainer: document.querySelector("#myChart") as HTMLElement,
    cellRange: {
      columns: ["date", "avgTemp"],
    },
    suppressChartRanges: true,
    chartType: "line",
  });
}

function dateFormatter(params: ValueFormatterParams) {
  return params.value
    ? params.value.toISOString().substring(0, 10)
    : params.value;
}

function toggleAxis() {
  const axisBtn = document.querySelector("#axisBtn") as any;
  axisBtn.textContent = axisBtn.value;
  axisBtn.value = axisBtn.value === "time" ? "category" : "time";

  const columnDefs: ColDef[] = getColumnDefs();
  columnDefs.forEach((colDef) => {
    if (colDef.field === "date") {
      colDef.chartDataType = axisBtn.value;
    }
  });

  gridApi!.setGridOption("columnDefs", columnDefs);
}

function formatDate(date: Date | number) {
  return Intl.DateTimeFormat("en-GB", {
    day: "2-digit",
    month: "short",
    year: undefined,
  }).format(new Date(date));
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).toggleAxis = toggleAxis;
}
```

[Live example: Time vs Category Axis](https://www.ag-grid.com/examples/integrated-charts-time-series/time-vs-category/typescript)

## Time Axis Configuration

A [Time Axis](https://www.ag-grid.com/charts/react/axes-types/#time) can be configured by setting `chartDataType = 'time'` on the column definition.

For the time axis to work correctly, the column must contain values in one of the following formats:

- `Date`
- `string` in ISO 8601 format
- `number` representing the numeric timestamp

Additionally, if `chartDataType` is not specified and the column contains `Date` values, it will automatically use a time axis.

The following snippet shows how different time series values can be configured to enable a time axis:

```js
const gridOptions = {
    columnDefs: [
        // date objects are treated as time by default
        { field: 'someDate' },
        { field: 'someIsoString', chartDataType: 'time' },
        { field: 'someTimestamp', chartDataType: 'time' },
    ],
    rowData: [
        {
            someDate: new Date('Mon Apr 17 2023 12:43:17'), // date object
            someIsoString: '2023-04-17T11:43:17.000Z', // ISO 8601 string
            someTimestamp: 1681735397000, // numeric timestamp (JavaScript format)
        },
        // ... more rows
    ],

    // other grid options ...
}
```

The following example demonstrates configuring numeric timestamps to use a time axis:

#### Time Axis Configuration

```ts
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  ClientSideRowModelModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  IntegratedChartsModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { getData } from "./data";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
]);

let gridApi: GridApi;

const gridOptions: GridOptions = {
  columnDefs: [
    { field: "timestamp", chartDataType: "time" },
    { field: "cpuUsage" },
  ],
  defaultColDef: { flex: 1 },
  cellSelection: true,
  popupParent: document.body,
  enableCharts: true,
  chartThemeOverrides: {
    area: {
      title: {
        enabled: true,
        text: "CPU Usage",
      },
      navigator: {
        enabled: true,
        height: 20,
        spacing: 25,
      },
      axes: {
        time: {
          label: {
            rotation: 315,
            format: "%H:%M",
          },
        },
        number: {
          label: {
            formatter: (params: any) => {
              // charts typings
              return params.value + "%";
            },
          },
        },
      },
    },
  },
  chartToolPanelsDef: {
    panels: ["data", "format"],
  },
  onGridReady: (params: GridReadyEvent) => {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  },
  onFirstDataRendered,
};

function onFirstDataRendered(params: FirstDataRenderedEvent) {
  params.api.createRangeChart({
    chartContainer: document.querySelector("#myChart") as HTMLElement,
    cellRange: {
      columns: ["timestamp", "cpuUsage"],
    },
    suppressChartRanges: true,
    chartType: "area",
  });
}

function formatTime(date: Date | number) {
  return Intl.DateTimeFormat("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  }).format(new Date(date));
}

gridApi = createGrid(
  document.querySelector<HTMLElement>("#myGrid")!,
  gridOptions,
);
```

[Live example: Time Axis Configuration](https://www.ag-grid.com/examples/integrated-charts-time-series/time-axis-config/typescript)

## Time Axis Combination Chart

A time axis can also be used in combination charts as shown in the following example.

For more details on how to configure a combination chart, see the [Range Chart API example](https://www.ag-grid.com/javascript-data-grid/integrated-charts-api-range-chart/#combination-charts).

#### Time Axis Combination Chart

```ts
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgAxisCaptionFormatterParams,
  AgCartesianSeriesTooltipRendererParams,
  AgCrosshairLabelRendererParams,
} from "ag-charts-types";
import {
  ClientSideRowModelModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  ValueParserParams,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  IntegratedChartsModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { getData } from "./data";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
]);

let gridApi: GridApi;

const gridOptions: GridOptions = {
  columnDefs: [
    {
      field: "date",
      chartDataType: "time",
      valueFormatter: (params) => params.value.toISOString().substring(0, 10),
    },
    { field: "rain", chartDataType: "series", valueParser: numberParser },
    { field: "pressure", chartDataType: "series", valueParser: numberParser },
    { field: "temp", chartDataType: "series", valueParser: numberParser },
  ],
  defaultColDef: { flex: 1 },
  cellSelection: true,
  popupParent: document.body,
  enableCharts: true,
  chartThemeOverrides: {
    common: {
      padding: {
        top: 45,
      },
      axes: {
        number: {
          title: {
            enabled: true,
            formatter: (params: AgAxisCaptionFormatterParams) => {
              return params.boundSeries.map((s) => s.name).join(" / ");
            },
          },
        },
        time: {
          crosshair: {
            label: {
              renderer: (params: AgCrosshairLabelRendererParams) => ({
                text: formatDate(params.value),
              }),
            },
          },
        },
      },
    },
    bar: {
      series: {
        strokeWidth: 2,
        fillOpacity: 0.8,
      },
    },
    line: {
      series: {
        strokeWidth: 5,
        strokeOpacity: 0.8,
      },
    },
  },
  onGridReady: (params: GridReadyEvent) => {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  },
  onFirstDataRendered,
};

function onFirstDataRendered(params: FirstDataRenderedEvent) {
  params.api.createRangeChart({
    chartContainer: document.querySelector("#myChart") as HTMLElement,
    cellRange: {
      columns: ["date", "rain", "pressure", "temp"],
    },
    suppressChartRanges: true,
    seriesChartTypes: [
      { colId: "rain", chartType: "groupedColumn", secondaryAxis: false },
      { colId: "pressure", chartType: "line", secondaryAxis: true },
      { colId: "temp", chartType: "line", secondaryAxis: true },
    ],
    chartType: "customCombo",
    aggFunc: "sum",
  });
}

function numberParser(params: ValueParserParams) {
  const value = params.newValue;
  if (value === null || value === undefined || value === "") {
    return null;
  }
  return parseFloat(value);
}

function formatDate(date: Date | number) {
  return Intl.DateTimeFormat("en-GB", {
    day: "2-digit",
    month: "short",
    year: undefined,
  }).format(new Date(date));
}

// set up the grid after the page has finished loading
gridApi = createGrid(
  document.querySelector<HTMLElement>("#myGrid")!,
  gridOptions,
);
```

[Live example: Time Axis Combination Chart](https://www.ag-grid.com/examples/integrated-charts-time-series/time-combination-chart/typescript)
