Date Axis

Date axis (DateAxis) is quite similar to the Value axis, except instead of numeric scale, it uses date and time scale.

Basically, if you have a series that is bound to a date/time values in data (via its own dataFields), you will need a Date axis to plot it on.

Just like Value axis, a Date axis will automatically select its scale based on the actual scope of date/time values in data.

It will also ensure that each data point is placed at exactly the position it has its date/time set on.

To demonstrate it all, let's refactor our demo from before to use days plotted on a Date axis, instead of categories.

let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
{
// ...
"xAxes": [{
"type": "DateAxis"
}]
}

IMPORTANT In order for series to be correctly plotted on a Date axis, it needs to set up proper dataFields, such as dateX or dateY.

MORE INFO Please refer to our "Series" article for more information about series' data fields.

Let's take a look at the updated example:

See the Pen amCharts V4: Date axis (1) by amCharts (@amcharts) on CodePen.24419

Natural time scale

As we briefly mentioned before, a Date axis will try to maintain a natural scale, even if data points come at irregular intervals.

Let's try to move one of our data points a few days away from the other ones, to create a gap:

See the Pen amCharts V4: Date axis (2) by amCharts (@amcharts) on CodePen.24419

As you can see, the last column moved away, creating "empty" entries in the Date axis, for the days the there is no data points for.

Data granularity

A date/time-based data can come at different intervals. For example, we could have just one entry per year, or we can have a data point every millisecond.

Date axis will do turn on its wits to determine the granularity by examining your actual data. So, if you have data points with a minute between them, the axis will determine the best granularity to use is a minute.

Data granularity affects how axis grid is drawn, and how labels are formatted. E.g. if you have a data point each day, it makes sense to display a grid line and a date label for each data point.

MORE INFO We will have a more detailed look at formatting of axis labels further down this article, in section "Label formatting".

Manually specifying data granularity

In some rare cases, when you have data coming in at irregular intervals, or where precise timestamp is important, even if your data points are logged only occasionally, you might need to explicitly specify the granularity of data for your Date axis to use.

In those cases you will use Date axis' setting baseInterval.

NOTE In fact, if you know the granularity of your data beforehand, it is encouraged to set baseInterval so that Date axis does not have to waste precious resources in trying to figure it our from your data.

It comes in a form of an object like this:

{   
"timeUnit": "minute",
"count": 5
}

A "timeUnit" identifies base time unit (second, minute, hour, day, etc.).

A "count" specifies how many "timeUnit" each data item comes at. Count parameter can be skipped, in which case Date axis will assume 1.

The above snippet actually serves as a hint to Date axis: "my data has a data point every 5 minutes".

Let's see what happens to our chart if we revert to data point per minute, rather than data point per day.

See the Pen amCharts V4: Date axis (3) by amCharts (@amcharts) on CodePen.24419

As you can see the chart automatically adjusted to our new minute-based data.

Let's say we need to emphasize that we have a second-based data, even though we just have one data point per minute.

dateAxis.baseInterval = {
"timeUnit": "second",
"count": 1
}
dateAxis.baseInterval = {
"timeUnit": "second",
"count": 1
}
{
// ...
"xAxes": [{
"type": "DateAxis",
"baseInterval": {
"timeUnit": "second",
"count": 1
}
}]
}

See the Pen amCharts V4: Date axis (4) by amCharts (@amcharts) on CodePen.24419

As you can see, we still have the same 3 columns, however they're now much smaller. This happens because we have instructed our Date axis that we need second-grade granularity. This means that every minute is now divvied up into 60 seconds, so our column now takes 1/60th of the width, allotted for the whole minute.

Notice, how labels are changed to accommodate seconds as well.

Formatting date and time

Normally, date and time across the chart is formatted using chart's DateFormatter, or more precisely, using format that is in its dateFormat property. More about that here.

That is not the case with Date axis.

The reason for this is that one format is not enough for a Date axis. You might need one format if your axis is displaying increments in days, and wholly different one for displaying time in seconds.

Furthermore, units displayed on Date axis may change dynamically, based on zoom, so formats must change just as well.

For example, your chart might be displaying year worth of daily data. At full zoom, Date axis will show only months:

January, February, March, etc.

Now, say you zoom in into February, so now your chart displays only 28 days, and reverts to showing only days:

1, 2, 3, etc.

Obviously, single format will not do in this case, hence Date axis having separate formats for each possible granularity of increments.

Those are set via Date axis' dateFormats and periodChangeDateFormats properties. More about the latter a bit later.

Setting date formats

As we mentioned earlier, a Date axis has a property dateFormats which is a dictionary associating each possible time unit like minute and day to a particular format.

It's a dictionary (which is an advanced object) which allows setting formats for each possible way to display date and time.

To set a time for specific time granularity, we use dateFormats.setKey(period, format) syntax.

For example, let's make our day-based labels, instead of default "Apr 20" and "Apr 21" display full month name, day and an appropriate ordinal. E.g. "April 20th", "April 21st", etc.

Looking at "Formatting date and time" article, we see that format option for the above would be "MMMM dt".

dateAxis.dateFormats.setKey("day", "MMMM dt");
dateAxis.dateFormats.setKey("day", "MMMM dt");
{
// ...
"xAxes": [{
"type": "DateAxis",
"dateFormats": {
"day": "MMMM dt"
}
}]
}

See the Pen amCharts V4: Formatting date axis labels by amCharts (@amcharts) on CodePen.24419

List of available time units

Period Format in default locale Example Format in us_EN Example
"millisecond" "mm:ss SSS" 25:00 500 "mm:ss SSS" 25:00 500
"second" "HH:mm:ss" 15:20:30 "hh:mm:ss a" 03:20:30 pm
"minute" "HH:mm" 15:20 "hh:mm a" 03:20 pm
"hour" "HH:mm" 15:20 "hh:mm a" 03:20 pm
"day" "MMM dd" Jan 09 "MMM dd" Jan 09
"week" "ww" 05 "ww" 05
"month" "MMM" Jan "MMM" Jan
"year" "yyyy" 2019 "yyyy" 2019

Period change format

Wait, we're not quite done here, yet.

Let's try a similar chart that instead of several days, spans several months.

See the Pen amCharts 4: Formatting date axis labels by amCharts team (@amcharts) on CodePen.0

What the...? Our chart had its dateFormats set for "day" to "MMMM dt". All labels seem to follow it except on: May 01.

Is it a bug? No. Let's look into what is going on.

Depending on the actual range and other settings, Date axis is using some base time unit for its increments.

In out case those are days.

It lists days using dateFormats and its "day" setting, until it comes to an end of the larger period - in this case month. When that happens, the first label in the larger period (month) is not formatted according to dateFormats but rather to periodChangeDateFormats.

While the rest of the labels were using dateFormats which we modified, the May 01 label looked into periodChangeDateFormats which we didn't touch, and came out using different format.

So, if you want your period change labels to look identical, you need to set it twice:

dateAxis.dateFormats.setKey("day", "MMMM dt");
dateAxis.periodChangeDateFormats.setKey("day", "MMMM dt");
dateAxis.dateFormats.setKey("day", "MMMM dt");
dateAxis.periodChangeDateFormats.setKey("day", "MMMM dt");
{
// ...
"xAxes": [{
"type": "DateAxis",
"dateFormats": {
"day": "MMMM dt"
},
"periodChangeDateFormats": {
"day": "MMMM dt"
}
}]
}

See the Pen amCharts 4: Formatting date axis labels by amCharts team (@amcharts) on CodePen.0

Why do we need two separate sets of formats anyway?

Good question!

Suppose we display a couple of years worth of daily data. Since there's no place to display 300+ labels for each day, our chart goes into "month" mode.

Our monthly labels would like something like this:

A bit misleading, huh?

That's why period change uses different format:

Now, since our first label in the year (January) uses different format we know precisely where and what year starts.

We can even modify it to show only year, since user will automatically assume January for the first month anyway. And, for extra clarity, let's make yearly labels bold.

dateAxis.periodChangeDateFormats.setKey("month", "[bold]yyyy[/]"); 
dateAxis.periodChangeDateFormats.setKey("month", "[bold]yyyy[/]");
{
// ...
"xAxes": [{
"type": "DateAxis",
"periodChangeDateFormats": {
"month": "[bold]yyyy[/]"
}
}]
}

See the Pen amCharts 4: Formatting date axis labels by amCharts team (@amcharts) on CodePen.0

Removing empty time units

Sometimes you won't want to display seconds, minutes, hours, days, or whatever your baseInterval is without data. For example in a stock option, you won't have any data over the weekends, because, well, there's no trading going on.

In that case you can go ahead and remove empty time units using axis' skipEmptyPeriods setting.

dateAxis.skipEmptyPeriods = true;
dateAxis.skipEmptyPeriods = true; 
{
// ...
"xAxes": [{
"type": "DateAxis",
// ...
"skipEmptyPeriods": true
}]
}

See the Pen amCharts V4: Date axis (5) by amCharts (@amcharts) on CodePen.24419

Related content