1

Using Google Charts, I need to plot duration in vertical axis in hh:mm format. Since hour value can be greater than 24 timeofday is not suitable.

<html>
<head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
        google.charts.load('current', { 'packages': ['corechart'] });
        google.charts.setOnLoadCallback(drawChart);
        function drawChart() {
            var data = new google.visualization.DataTable();
            data.addColumn('string', 'Topping');
            data.addColumn('timeofday', 'Duration');
            data.addRows([
                ['Me', [23,59,0]],
                ['My Boss', [47,59,0]]
            ]);
            var options = {
                'title': 'How Long We Ate Pizza',
                'width': 400,
                'height': 300,
                'vAxis': { 'format':'HH:mm'}
            };
            var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
            chart.draw(data, options);
        }
    </script>
</head>
<body>
    <div id="chart_div"></div>
</body>
</html>

Graph showing 23:59 for My Boss. Result graph If I format it to string, I get Data column(s) for axis #0 cannot be of type string error.

Is there any way I can handle it?

WhiteHat
  • 59,912
  • 7
  • 51
  • 133
Nandan Acharya
  • 900
  • 2
  • 12
  • 24
  • 1
    it's possible, you can use object notation to provide the value of the duration (`v:`) and the formatted value of the duration (`f:`) --> so if our values are in minutes, we could have --> `{v: 190, f: '03:10'}` – WhiteHat Dec 11 '19 at 13:15
  • if you want to provide a sample of the data and the chart code, I can provide a working example... – WhiteHat Dec 11 '19 at 13:16
  • I have added sample code. – Nandan Acharya Dec 11 '19 at 16:10

2 Answers2

1

to build the chart dynamically, from timeofday values,
first use a data view to convert timeofday to minutes

// use calculated column to convert time of day to duration in minutes
var view = new google.visualization.DataView(data);
view.setColumns([0, {
  calc: function (dt, row) {
    // initialize variables
    var minutesFormat = '';
    var minutesValue = 0;
    var timeofday = dt.getValue(row, 1);

    // calculate total minutes
    timeofday.forEach(function (value, index) {
      // determine time part
      switch (index) {
        // hours
        case 0:
          minutesFormat += value;
          minutesValue += (value * 60);
          break;

        // minutes
        case 1:
          minutesFormat += ':' + value;
          minutesValue += value;
          break;

        // seconds
        case 2:
          minutesValue += (value / 60);
          break;

        // miliseconds
        case 3:
          minutesValue += (value / 60000);
          break;
      }
    });

    // build object notation
    return {
      v: minutesValue,
      f: minutesFormat
    };
  },
  label: data.getColumnLabel(1),
  type: 'number'
}]);

then for the y-axis ticks,
first, get the max number of minutes.

// get range of duration in muntes
var range = view.getColumnRange(1);  // range.max

then we need to determine the number of hours to round to (10, 100, 1000)

// determine max number of hours for y-axis
var maxHours = Math.ceil(range.max / 60);
var roundTo = parseInt('1' + Array(maxHours.toFixed(0).length).join('0'));
var maxHours = Math.ceil((range.max / 60) / roundTo) * roundTo;

then build our ticks...

// build y-axis ticks
var ticks = [];
for (var hour = 0; hour <= maxHours; hour += roundTo) {
  ticks.push({
    v: hour * 60,
    f: hour + ':00'
  });
}

see following working snippet...

google.charts.load('current', {
  packages: ['corechart']
}).then(function () {
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'Topping');
  data.addColumn('timeofday', 'Duration');
  data.addRows([
    ['Me', [23,59,0]],
    ['My Boss', [47,59,0]]
  ]);

  // use calculated column to convert time of day to duration in minutes
  var view = new google.visualization.DataView(data);
  view.setColumns([0, {
    calc: function (dt, row) {
      // initialize variables
      var minutesFormat = '';
      var minutesValue = 0;
      var timeofday = dt.getValue(row, 1);

      // calculate total minutes
      timeofday.forEach(function (value, index) {
        // determine time part
        switch (index) {
          // hours
          case 0:
            minutesFormat += value;
            minutesValue += (value * 60);
            break;

          // minutes
          case 1:
            minutesFormat += ':' + value;
            minutesValue += value;
            break;

          // seconds
          case 2:
            minutesValue += (value / 60);
            break;

          // miliseconds
          case 3:
            minutesValue += (value / 60000);
            break;
        }
      });

      // build object notation
      return {
        v: minutesValue,
        f: minutesFormat
      };
    },
    label: data.getColumnLabel(1),
    type: 'number'
  }]);

  // get range of duration in muntes
  var range = view.getColumnRange(1);

  // determine max number of hours for y-axis
  var maxHours = Math.ceil(range.max / 60);
  var roundTo = parseInt('1' + Array(maxHours.toFixed(0).length).join('0'));
  var maxHours = Math.ceil((range.max / 60) / roundTo) * roundTo;

  // build y-axis ticks
  var ticks = [];
  for (var hour = 0; hour <= maxHours; hour += roundTo) {
    ticks.push({
      v: hour * 60,
      f: hour + ':00'
    });
  }

  var options = {
    title: 'How Long We Ate Pizza',
    width: 400,
    height: 300,
    vAxis: {
      ticks: ticks
    }
  };

  var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  chart.draw(view, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
WhiteHat
  • 59,912
  • 7
  • 51
  • 133
0

Thanks to WhiteHat comment and this answer.

Used object notation while adding the values and ticks.

data.addRows([
    ['Me', { v: 1439, f: '23:59' }],
    ['My Boss', { v: 2879, f: '47:59' }]
]);
var options = {
    'title': 'How Long We Ate Pizza',
    'width': 400,
    'height': 300,
    'vAxis': {
        ticks: [{ v: 720, f: '12:00' }, { v: 1440, f: '24:00' }, { v: 2160, f: '36:00' }, { v: 2880, f: '48:00' }]
    }
};
Nandan Acharya
  • 900
  • 2
  • 12
  • 24