If you have worked with Highcharts, you know that it’s sometimes difficult to find all the right incantations to get it to do your biding.

One that particularly stumped me was the datetime axis type. I had regular data, for example some metric per month, with my points having an X value of the first day of each month. At first, everything seems fine:

$(function () {
    title: {
      text: 'Everything seems fine',
    xAxis: {
      type: 'datetime'
    series: [{
      name: 'A fine series',
      data: [
        [moment('2014-01-01').valueOf(), 7.0],
        [moment('2014-02-01').valueOf(), 6.9],
        [moment('2014-03-01').valueOf(), 9.5],
        [moment('2014-04-01').valueOf(), 14.5],
        [moment('2014-05-01').valueOf(), 18.2],
        [moment('2014-06-01').valueOf(), 21.5],
        [moment('2014-07-01').valueOf(), 25.2],
        [moment('2014-08-01').valueOf(), 26.5],
        [moment('2014-09-01').valueOf(), 23.3],
        [moment('2014-10-01').valueOf(), 18.3],
        [moment('2014-11-01').valueOf(), 13.9],
        [moment('2014-12-01').valueOf(), 9.6]

The problem

So far, so good. But then, you add a date format for the labels, because your client doesn’t like Highcharts’ default format:

    // ...
    xAxis: {
      // ...
      labels: {
        formatter: function() {
          return moment(this.value).format("YYYY-MM-DD");
    // ...

Furthermore, your client complains that sometimes the labels repeat themselves when he generates the report:


Well, as i’ve found, there are actually two different issues:

  1. There is an offset between the point on the chart and the tick on the axis (as evidenced by the first chart).
  2. The labels repeat themselves because Highcharts falls on a smaller scales (days, not months), and your date format hides this from you.

Problem #1

Let me illustrate point 1 with a more obvious example:

You may not be seeing the same thing as me, but I get labels offset by -4 hours, which look suspiciously like a UTC vs localized dates issue. After trying a few solutions mostly involving Moment.js wizardry (amazing library, by the way), i stumbled across this. The solution is quite simple:

// Add this before rendering your chart
  global: {
    useUTC: false

Problem #2

Now, on to issue #2. As before, let’s have an example to better illustrate the issue:

This one stumped me a lot longer than issue #1. I tried various possible solutions, including defining the axis as a ‘category’ axis (don’t go there, you may not come back), but I finally found the solution, again in the Highcharts documentation:

    // ...
    xAxis: {
      // ...
      minTickInterval: moment.duration(1, 'month').asMiliseconds()
      //                                   ^^^^^ or whatever your interval is
    // ...

And voilà, the beautiful charts you’ve always wanted:


Highcharts is a very powerful library, but it can be hard sometimes to get it to do exactly what you want. However, as we’ve demonstrated here, there’s usually a way. Feel free to tweet me any question.