Lleims
Lleims

Reputation: 1353

Why are changing the time value of my axis (moment.js)?

I am working with chart.js and moment.js to show a chart with x-axis as time.

I had some problems with plotting this axis and I asked this question.

@uminder solved it. This is his code,

var sData = {
  datasets: [{
    label: 'Dataset1',
    data: [{
        x: '09:00',
        y: 88
      }, {
        x: '09:10',
        y: 89
      }, {
        x: '09:13',
        y: 86
      }, {
        x: '09:23',
        y: 86
      },
      {
        x: '09:26',
        y: 85
      }, {
        x: '09:29',
        y: 83
      }
    ]
  }, {
    label: 'Dataset2',
    data: [{
        x: '09:02',
        y: 88
      }, {
        x: '09:13',
        y: 89
      }, {
        x: '09:14',
        y: 86
      }, {
        x: '09:20',
        y: 86
      },
      {
        x: '09:24',
        y: 85
      }, {
        x: '09:29',
        y: 83
      }
    ]
  }]
}

sData.datasets[0].data = formatData(sData.datasets[0].data)
sData.datasets[1].data = formatData(sData.datasets[1].data)

function formatData(oldData) {
  var newData = []
  for (var i = 0; i < oldData.length; i++) {
    var currentData = {}
    currentData.x = moment(oldData[i].x, "HH:mm")
    currentData.y = oldData[i].y
    newData.push(currentData)
  }
  return newData
}

var options = {
  responsive: true,
  scales: {
    xAxes: [{
      type: 'time',
    }]
  },
  tooltips: {
    callbacks: {
      title: (tooltipItem, data) => moment(tooltipItem[0].label).format('HH:mm')
    }
  }
}

var ctx = document.getElementById('bateria_graf').getContext('2d');
let chart = new Chart(ctx, {
  type: 'line',
  data: sData,
  options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="bateria_graf"></canvas>

The problem is that when I execute the snippet, the x-axis appears like shown in the following image,

enter image description here

When I paste his solution in my program, it appears like the following image,

enter image description here

and when I pass my own datasets it appears like this,

enter image description here

Why is the format changing evertime? Why is it showing the date of today? I only want hour:minute in 24H format.

The datatsets in the third image that I'm passing are like this,

[{
  'label': 'Node1',
  'borderColor': '#4c59b4',
  'data': [{'x': '12:22', 'y': 86}, {'x': '12:32', 'y': 86}, {'x': '12:43', 'y': 85}, {'x': '12:53', 'y': 85}]
}, {
  'label': 'Node2',
  'borderColor': '#786f91',
  'data': [{'x': '09:08', 'y': 86}, {'x': '09:19', 'y': 86}, {'x': '09:29', 'y': 86}, {'x': '09:39', 'y': 86}, {'x': '09:49', 'y': 86}, {'x': '10:00', 'y': 86}, {'x': '10:10', 'y': 86}, {'x': '10:20', 'y': 86}, {'x': '10:30', 'y': 86}, {'x': '10:40', 'y': 86}, {'x': '10:51', 'y': 86}, {'x': '11:01', 'y': 86}, {'x': '11:11', 'y': 86}, {'x': '11:21', 'y': 86}, {'x': '11:31', 'y': 86}, {'x': '11:42', 'y': 86}, {'x': '11:52', 'y': 86}, {'x': '12:02', 'y': 86}, {'x': '12:12', 'y': 86}, {'x': '12:22', 'y': 86}, {'x': '12:32', 'y': 86}, {'x': '12:42', 'y': 86}, {'x': '12:52', 'y': 86}, {'x': '13:03', 'y': 86}, {'x': '13:13', 'y': 86}, {'x': '13:24', 'y': 86}, {'x': '13:34', 'y': 86}, {'x': '13:44', 'y': 86}, {'x': '13:54', 'y': 86}, {'x': '14:04', 'y': 86}, {'x': '14:14', 'y': 86}, {'x': '14:24', 'y': 86}, {'x': '14:35', 'y': 86}, {'x': '14:45', 'y': 86}, {'x': '14:55', 'y': 86}, {'x': '15:05', 'y': 87}, {'x': '15:16', 'y': 87}, {'x': '15:26', 'y': 87}, {'x': '15:46', 'y': 87}, {'x': '16:07', 'y': 87}, {'x': '16:17', 'y': 87}, {'x': '16:27', 'y': 87}]
}]

Upvotes: 0

Views: 144

Answers (1)

uminder
uminder

Reputation: 26150

To force your chart to always display time units in the desired format, you can define the time unit as follows.

xAxes: [{
   type: 'time',
      time: {
         unit: 'minute'
      }
   }]

Note that the default display format of time unit 'minute' is 'h:mm a' (i.e. "11:44 am"). In case, you want to define another format, you may do it using displayFormats.

xAxes: [{
      type: 'time',
      time: {
        displayFormats: {
          minute: 'h:mm'
        }
      }      
    }]

This results in the following runnable code snippet:

var sData = {
  datasets: [{
    'label': 'Node1',
    'borderColor': '#4c59b4',
    'data': [{'x': '12:22', 'y': 86}, {'x': '12:32', 'y': 86}, {'x': '12:43', 'y': 85}, {'x': '12:53', 'y': 85}]
  }, {
    'label': 'Node2',
    'borderColor': '#786f91',
    'data': [{'x': '09:08', 'y': 86}, {'x': '09:19', 'y': 86}, {'x': '09:29', 'y': 86}, {'x': '09:39', 'y': 86}, {'x': '09:49', 'y': 86}, {'x': '10:00', 'y': 86}, {'x': '10:10', 'y': 86}, {'x': '10:20', 'y': 86}, {'x': '10:30', 'y': 86}, {'x': '10:40', 'y': 86}, {'x': '10:51', 'y': 86}, {'x': '11:01', 'y': 86}, {'x': '11:11', 'y': 86}, {'x': '11:21', 'y': 86}, {'x': '11:31', 'y': 86}, {'x': '11:42', 'y': 86}, {'x': '11:52', 'y': 86}, {'x': '12:02', 'y': 86}, {'x': '12:12', 'y': 86}, {'x': '12:22', 'y': 86}, {'x': '12:32', 'y': 86}, {'x': '12:42', 'y': 86}, {'x': '12:52', 'y': 86}, {'x': '13:03', 'y': 86}, {'x': '13:13', 'y': 86}, {'x': '13:24', 'y': 86}, {'x': '13:34', 'y': 86}, {'x': '13:44', 'y': 86}, {'x': '13:54', 'y': 86}, {'x': '14:04', 'y': 86}, {'x': '14:14', 'y': 86}, {'x': '14:24', 'y': 86}, {'x': '14:35', 'y': 86}, {'x': '14:45', 'y': 86}, {'x': '14:55', 'y': 86}, {'x': '15:05', 'y': 87}, {'x': '15:16', 'y': 87}, {'x': '15:26', 'y': 87}, {'x': '15:46', 'y': 87}, {'x': '16:07', 'y': 87}, {'x': '16:17', 'y': 87}, {'x': '16:27', 'y': 87}]
  }]
}

sData.datasets[0].data = formatData(sData.datasets[0].data)
sData.datasets[1].data = formatData(sData.datasets[1].data)

function formatData(oldData) {
  var newData = []
  for (var i = 0; i < oldData.length; i++) {
    var currentData = {}
    currentData.x = moment(oldData[i].x, "HH:mm")
    currentData.y = oldData[i].y
    newData.push(currentData)
  }
  return newData
}

var options = {
  responsive: true,
  scales: {
    xAxes: [{
      type: 'time',
      time: {
        unit: 'minute'
      }
    }]
  },
  tooltips: {
    callbacks: {
      title: (tooltipItem, data) => moment(tooltipItem[0].label).format('HH:mm')
    }
  }
}

var ctx = document.getElementById('bateria_graf').getContext('2d');
let chart = new Chart(ctx, {
  type: 'line',
  data: sData,
  options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="bateria_graf"></canvas>

UPDATE

NEA made the following comment to this answer:

(...) I don't understand is why is printing, before the time the day of today. This is confusing, because my info is not from today (...).

The reason is that in above code, the time is parsed using Moment.js.

moment(oldData[i].x, "HH:mm")

When the parsed string does not contain information about the date, Moment.js assumes it to be of the current date. It has to make an assumption because the parsed object is basically a wrapper for Date. Please run the code snippet below and check the console output.

const m = moment("11:44", "HH:mm");
console.log(m);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

Upvotes: 2

Related Questions