chartjs / chartjs-adapter-luxon

Luxon adapter for Chart.js
MIT License
33 stars 22 forks source link

Unable to parse Unix millisecond time #51

Closed chrissnell-okta closed 2 years ago

chrissnell-okta commented 2 years ago

Hi,

I am trying to parse time that's stored in Unix millisecond format (integer) in JSON and getting this error:

Uncaught (in promise) Error: fromMillis requires a numerical input, but received a string with value 11:55:00.000 PM

This is very strange because I'm pretty dang certain that my time is formatted correctly and indeed, when I do a console.log(thsiodata), I can see that it is formatted correctly.

Here is the code in question:

const weatherURL = "https://carlisleweather.com/rest/span/24h";

function makeGraphConfig(label,dataKey) {
    graphData = {
        datasets: [{
            label: label,
            data: fetchData,
            fill: false,
            borderColor: 'rgb(75, 192, 192)',
            tension: 0.1
        }]
    }

    graphConfig = {
        type: "line",
        data: graphData,
        options: {
            responsive: false,
            maintainAspectRatio: true,
            elements:{
                point:{
                    borderWidth: 0,
                    radius: 10,
                    backgroundColor: 'rgba(0,0,0,0)'
                }
            },
            scales: {
                x: {
                    type: 'time',
                    ticks: {
                        callback: function(val, index) {
                            return index % 20 === 0 ? this.getLabelForValue(val) : '';
                        }
                    }
                }
            },
            plugins: {
                decimation: {
                    enabled: true,
                    threshold: 200
                }
            },
            parsing: {
                xAxisKey: "ts",
                yAxisKey: dataKey
            }
        }   
    }

    return graphConfig

}

getData();

async function getData() {
    axios
        .get(weatherURL,{}).then(function (response) {
                fetchData = response.data;
                console.log("wx data:", fetchData)
                var outsideTemperatureConfig = makeGraphConfig("Outside Temperature", "otemp");
                const tempCtx = document.getElementById('outsideTemperatureChart').getContext('2d');
                const outsideTemperatureChart = new Chart(tempCtx, outsideTemperatureConfig);
            }
        )
};

I'm pulling in the adapter like this:

    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@^3"></script>
    <script src="https://cdn.jsdelivr.net/npm/luxon@^2"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@^1"></script>

You can see the live data here: https://carlisleweather.com/rest/span/1h

I'm very new to frontend work and Javascript in general. Is there something I'm missing about how JS interprets timestamps?

stockiNail commented 2 years ago

@chrissnell-okta it's not a problem of the adapter but the issue is on the ticks.callback. The val argument is already the formatted date value therefore you should not need to ask to the scale to have the label value by a timestamp in string format.

I tried your sample with the following callbacks:

ticks: {
  callback: function(val) {
    return index % 20 === 0 ? val : '';
  }
}

l2

I have also tried to remove the callback, setting the time unit to 'hour' (to show the hour of timestamp), leaving CHART.JS to display the ticks with its rules:

scales: {
  x: {
    type: 'time',
    time: {
      unit: 'hour',
    },
  }
}

l1

stockiNail commented 2 years ago

@chrissnell-okta I have seen that in the https://carlisleweather.com/, the chart has got ticks at the minute 00 every 4 hours.

If you wan to do the same, you could define your scales as following:

scales: {
  x: {
    type: 'time',
    time: {
      unit: 'minute'
    },
    ticks: {
      callback: function(val) {
        if (val.endsWith('00') && val.substring(0, 2) % 4 === 0) { 
          return val;
        }
      }
    }
  }
},

l3

chrissnell-okta commented 2 years ago

Thank you so much, @stockiNail !

It would be great if these could be added to an example in the project README, since my ticks callback was straight out of the Chart.js docs which, I think, many rookies like me will simply copy.

Thanks again.

stockiNail commented 2 years ago

It would be great if these could be added to an example in the project README, since my ticks callback was straight out of the Chart.js docs which, I think, many rookies like me will simply copy.

@chrissnell-okta I think this note it shouldn't be included in this project because this project is providing an adapter which is "only" providing a normalization for CHART.JS to invoke the datetime services of Luxon. CHART.JS can use other datetime libraries and this layer can provide the right abstraction from the under layer library.

Going to CHART.JS, the example you used it's related to category scale (https://www.chartjs.org/docs/latest/samples/scale-options/ticks.html#tick-configuration) and not for all scale types.