Home Forums Report Bugs When summer time ends Charts axis labelFormatter “skips” an entire hour

When summer time ends Charts axis labelFormatter “skips” an entire hour

Viewing 4 posts - 1 through 4 (of 4 total)
  • #35949

    Hi team,

    We are using Charts for a customer in their web application. As both the customer and us are placed in Spain we will be switching from summer time to standard time on October 31, 3:00 AM, when it will be again 2:00 AM. Changing from DST to non-DST times seems to be causing trouble to how Charts represents time in an axis. Let’s see an example:

    DST to winter time example

    As we can see here, axisX has introduced a gap the size of an hour (let’s ignore the fact that there should be an additional mark after “2:30:00”). You can run this example live here but be aware that it may show different results if your locale does not observe DST or observes DST in a different day or time. Therefore, this example is best run in CEST regions.

    Here’s another example from our customer’s live environment:

    Live example showing DST to standard time issues

    This one is a bit different. Here we are processing labelFormatter to show times in UTC instead of local time. As you can see, the markers are missing from 1:00 AM to 2:00 AM UTC, which would correspond to 2-3 AM, Madrid time. On the other hand, the data is plotted correctly, and the hovered timestamp is shown in the last column of the green box as it should be.

    I have a clue that this issue might be related to a conversion between local times and an internal representation in UTC times. In the European Union we have to delay time one hour on the last Sunday of October, so we have 2:00-2:59 AM twice. The problem is, of course, that a local time like “2021-10-31 02:30:00” would have two representations in UTC, because UTC does not observe DST. I don’t know how Charts works internally but the fact that the axis “skips” an hour might be just a proportional way to represent the actual times it is able to “compute”.

    I don’t think there’s anything I can do about the first example, but as we are using UTC in the second one I have tried everything to force Charts to draw the “missing” labels, from 1 AM to 2 AM, to no avail. If I could find a way to draw them it would be fine and the customer would be happy.

    Is there anything I could do to overcome this issue, at least in our live example, or is this an actual bug with more serious implications in terms of how Charts works internally?

    Thank you very much for your help, best regards.



    We are looking into your query and will get back to you at the earliest.

    Indranil Deo
    Team CanvasJS



    I have hacked my way to get a working example using our customer’s data. I used the minified library for the old version they have in their website so please excuse me if the variable names don’t match the current ones in the most recent version.

    Our starting point will be the function “E.prototype.createLabels”, which controls how the labels will be created. I will modify this block a bit (I have formatted it so I could know what the “for” was doing):

    if ("axisX" === this.type && "dateTime" === this.chart.plotInfo.axisXValueType)
        for (
            this.intervalStartPosition = this.getLabelStartPoint(new Date(this.viewportMinimum), this.intervalType, this.interval),
            d = taNew(this.viewportMaximum, this.interval, this.intervalType),
            b = this.viewportMinimum;
            b < d;
            b = taNew(b, this.interval, this.intervalType)
            a = b, a = this.labelFormatter ? this.labelFormatter({
                chart: this.chart._publicChartReference,
                axis: this._options,
                value: b,
                label: this.labels[b] ? this.labels[b] : null
            }) : "axisX" === this.type && this.labels[a] ? this.labels[a] : ra(b, this.valueFormatString, this.chart._cultureInfo), a = new M(this.ctx, {
                x: 0,
                y: 0,
                maxWidth: e,
                maxHeight: g,
                angle: this.labelAngle,
                text: this.prefix + a + this.suffix,
                horizontalAlign: "left",
                fontSize: this.labelFontSize,
                fontFamily: this.labelFontFamily,
                fontWeight: this.labelFontWeight,
                fontColor: this.labelFontColor,
                fontStyle: this.labelFontStyle,
                textBaseline: "middle"
            }), this._labels.push({
                position: b,
                textBlock: a,
                effectiveHeight: null

    I am also calling a new function, “taNew”, which is not really optimal but will help us do the trick:

    function taNew(a, c, b){
        if ("millisecond" === b) return a + 1 * c;
        if ("second" === b) return a + 1 * 1000 * c;
        if ("minute" === b) return a + 1 * 1000 * 60 * c;
        if ("hour" === b) return a + 1 * 1000 * 60 * 60 * c;
        if ("day" === b) return a + 1 * 1000 * 60 * 60 * 24 * c;
        if ("week" === b) return a + 1 * 1000 * 60 * 60 * 24 * 7 * c;
        if ("month" === b) return a + 1 * 1000 * 60 * 60 * 24 * 30 * c;
        if ("year" === b) return a + 1 * 1000 * 60 * 60 * 24 * 365 * c;

    Please note that I am not creating Date objects in the process because I will leave this task to my own code when I create the chart. With these changes, the result is this:

    The chart with the changes applied

    We can see that axisX now has all the marks from 11PM to 4AM (I guess it shifts one second because my code is not perfect, but it is a real progress). Since I never use “new Date()” in the library the variables are integers representing timestamps and I leave the task to transform them into readable times to a custom function in labelFormatter. Thus, the axis is not “broken” anymore.

    Hope this helps you debugging.




    Glad that modifying a part of the source-code worked for you. Since you are making changes in the source-code, we would suggest you to test the updated code with different use cases of date-time axis to make sure it doesn’t affect other functionalities that you are using.

    Also, we will revisit & reconsider this behavior in future releases.

    Indranil Deo
    Team CanvasJS

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.