Search code examples
javascripthtmlcssamchartsamcharts4

amcharts4 Format date from unix timestamp


I have a simple area chart and I would like to show the right date with hours and minutes. I have a const for converting unix timestamp :

const formatDate = inputDate => {
    const date1 = new Date(inputDate * 1000);

    let day = date1.getDate();
    let month = date1.getMonth() + 1;
    const year = date1.getFullYear();
    if (day < 10) {
      day = '0' + dd;
    }
    if (month < 10) {
      month = '0' + month;
    }
    const formattedDate = day + '/' + month + '/' + year;
    return formattedDate;
}

Here is my full code :

am4core.useTheme(am4themes_animated);

var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.dataSource.url = "https://api.myjson.com/bins/8se3o";

const formatDate = inputDate => {
    const date1 = new Date(inputDate * 1000);

    let day = date1.getDate();
    let month = date1.getMonth() + 1;
    const year = date1.getFullYear();
    if (day < 10) {
      day = '0' + dd;
    }
    if (month < 10) {
      month = '0' + month;
    }
    const formattedDate = day + '/' + month + '/' + year;
    return formattedDate;
}

chart.data = chart.data.map(element => {
  element.time = formatDate(element.time)
  return element;
});




var dateAxis = chart.xAxes.push(new am4charts.DateAxis());

var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;

var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.dateX = "time";
series.name = "outDiff";
series.dataFields.valueY = "outDiff";
series.tooltipHTML = "<span style='font-size:14px; color:#000000;'><b>{valueY.value}</b></span>";
series.tooltipText = "[#000]{valueY.value}[/]";
series.tooltip.background.fill = am4core.color("#FFF");
series.tooltip.getStrokeFromObject = true;
series.tooltip.background.strokeWidth = 3;
series.tooltip.getFillFromObject = false;
series.fillOpacity = 0.6;
series.strokeWidth = 2;
series.stacked = true;

var series2 = chart.series.push(new am4charts.LineSeries());
series2.name = "inDiff";
series2.dataFields.dateX = "time";
series2.dataFields.valueY = "inDiff";
series2.tooltipHTML = "<span style='font-size:14px; color:#000000;'><b>{valueY.value}</b></span>";
series2.tooltipText = "[#000]{valueY.value}[/]";
series2.tooltip.background.fill = am4core.color("#FFF");
series2.tooltip.getFillFromObject = false;
series2.tooltip.getStrokeFromObject = true;
series2.tooltip.background.strokeWidth = 3;
series2.sequencedInterpolation = true;
series2.fillOpacity = 0.6;
series2.stacked = true;
series2.strokeWidth = 2;

chart.cursor = new am4charts.XYCursor();
chart.cursor.xAxis = dateAxis;
chart.scrollbarX = new am4core.Scrollbar();


chart.legend = new am4charts.Legend();
chart.legend.position = "top";
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

#chartdiv {
  width: 100%;
  height: 500px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>

All data from time key are from todays date (19/04/2019)


Solution

  • There are couple of things wrong with your code.

    First, amCharts expects dates to be sorted in ascending order. Your data is currently out of order, causing the chart to look weird.

    Second, you don't need to format your data in string format. You can still use your timestamp (provided that you multiply by 1000 seconds) and use the chart's dateFormatter to parse it through the "x" code in inputDateFormatter, as documented here.

    Since you're using dataSource, you can use the parseended event to manipulate your data before it is assigned to the chart like so:

    chart.dataSource.events.on("parseended", function(ev) {
      // parsed data is assigned to data source's `data` property
      var data = ev.target.data;
      data.sort(function(lhs, rhs) {
        return lhs.time - rhs.time;
      });
      data.forEach(function(item) {
        item.time *= 1000;
      });
    });
    
    chart.dateFormatter.inputDateFormat = "x";
    

    To change the dates, you have to modify your date axis' dateFormats and periodChangeDateFormats list objects and set the appropriate date format for the period(s) you want to reformat. Since your data is in minutes, you'll want to call setKey on the minutes period and adjust accordingly as documented here, for example:

    dateAxis.dateFormats.setKey("minute", "MMM dd\nHH:mm");
    dateAxis.periodChangeDateFormats.setKey("minute", "MMM dd\nHH:mm");
    

    Fully updated code below:

    am4core.useTheme(am4themes_animated);
    
    var chart = am4core.create("chartdiv", am4charts.XYChart);
    chart.dataSource.url = "https://api.myjson.com/bins/8se3o";
    chart.dataSource.events.on("parseended", function(ev) {
      // parsed data is assigned to data source's `data` property
      var data = ev.target.data;
      data.sort(function(lhs, rhs) {
        return lhs.time - rhs.time;
      });
      data.forEach(function(item) {
        item.time *= 1000;
      });
    });
    
    chart.dateFormatter.inputDateFormat = "x";
    
    
    var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
    dateAxis.dateFormats.setKey("minute", "MMM dd\nHH:mm");
    dateAxis.periodChangeDateFormats.setKey("minute", "MMM dd\nHH:mm");
    
    var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
    valueAxis.tooltip.disabled = true;
    
    var series = chart.series.push(new am4charts.LineSeries());
    series.dataFields.dateX = "time";
    series.name = "outDiff";
    series.dataFields.valueY = "outDiff";
    series.tooltipHTML = "<span style='font-size:14px; color:#000000;'><b>{valueY.value}</b></span>";
    series.tooltipText = "[#000]{valueY.value}[/]";
    series.tooltip.background.fill = am4core.color("#FFF");
    series.tooltip.getStrokeFromObject = true;
    series.tooltip.background.strokeWidth = 3;
    series.tooltip.getFillFromObject = false;
    series.fillOpacity = 0.6;
    series.strokeWidth = 2;
    series.stacked = true;
    
    var series2 = chart.series.push(new am4charts.LineSeries());
    series2.name = "inDiff";
    series2.dataFields.dateX = "time";
    series2.dataFields.valueY = "inDiff";
    series2.tooltipHTML = "<span style='font-size:14px; color:#000000;'><b>{valueY.value}</b></span>";
    series2.tooltipText = "[#000]{valueY.value}[/]";
    series2.tooltip.background.fill = am4core.color("#FFF");
    series2.tooltip.getFillFromObject = false;
    series2.tooltip.getStrokeFromObject = true;
    series2.tooltip.background.strokeWidth = 3;
    series2.sequencedInterpolation = true;
    series2.fillOpacity = 0.6;
    series2.stacked = true;
    series2.strokeWidth = 2;
    
    chart.cursor = new am4charts.XYCursor();
    chart.cursor.xAxis = dateAxis;
    chart.scrollbarX = new am4core.Scrollbar();
    
    
    chart.legend = new am4charts.Legend();
    chart.legend.position = "top";
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    }
    
    #chartdiv {
      width: 100%;
      height: 500px;
    }
    <script src="https://www.amcharts.com/lib/4/core.js"></script>
    <script src="https://www.amcharts.com/lib/4/charts.js"></script>
    <script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
    <div id="chartdiv"></div>