blankface
blankface

Reputation: 6347

Calculating time difference for sets of streaming data

I have the following function that renders a row based on streaming SignalR data coming from another component:

let prev
let next

renderRow = () = {
    this.props.incomingData.map(item => {
        return (
            <tr>
                <td>{item.time}</td> //00:00:00 format
                <td>{this.calculateSecondsTaken()}</td> //should show the time difference in seconds
                <td>{item.event}</td>
                <td>{item.message} <br/>{item.outputURL}</td>
            </tr>
        )
    })
}

I'm trying to get the time difference for each data row based on the item.time attribute value by subtracting current time from previous time (in the row).

//calculates the difference between the previous and the incoming (next) time value to give the time taken
//for the current row's data to come in.
calculateSecondsTaken = (prev, next) => {
    next - prev;
}

I know in the above function it has to be some sort of a subtraction based on previous and next values of time but I can't quite pin down the logic of it. For instance, what would the difference be for the very first row etc.

Edit: The data streaming component is as follows

deploymentEventMessageReceived = (item: DeploymentEvent) => {
    let dataset = {
        time: item.UtcNowPrettyText, //this is the time value
        event: item.EventName,
        message: item.Message,
        outputURL: item.OutputUrl
    }
    let newDataArray = this.state.receivedData.concat(dataset);

    this.setState({
        receivedData: newDataArray
    });
}

deploymentEventMessageReceived() in turn gets called inside the function where I'm connecting to SignalR.

Edit 2 updated (working version):

deploymentEventMessageReceived = (item: DeploymentEvent) => {
  let lastEntryTime;
  newArray = newArray.concat(item);

  if (newArray.length == 1) {
    lastEntryTime = moment(newArray[newArray.length - 1].UtcNowPrettyText)
  } else {
    lastEntryTime = moment(newArray[newArray.length - 2].UtcNowPrettyText)
  }

  timeDiff = moment(item.UtcNowPrettyText).diff(lastEntryTime, "seconds");

  //create new object with the addition of TimeDifference attribute
  let dataset = {
    UtcNowPrettyText: item.UtcNowPrettyText,
    EventName: item.EventName,
    Message: item.Message,
    OutputUrl: item.OutputUrl,
    TimeDifference: timeDiff
  }

  //store it in a new array
  finalDatasetArray = finalDatasetArray.concat(dataset);

  this.setState({
    receivedData: finalDatasetArray
  });
}

Inside render() of data streaming component

<RenderRow receivedData={this.state.receivedData} />

Any help is appreciated.

Upvotes: 1

Views: 128

Answers (1)

Andrew
Andrew

Reputation: 7555

I would implement a time difference calculation this way: I keep track of Date.now(), which I don't render but keep it in each entry so I can perform math on it. I don't know how you're planning on rendering the time difference, but I put it in this.state in my example.

deploymentEventMessageReceived = (item) => {
    let dataset = {
        time: item.UtcNowPrettyText, //this is the time value
        event: item.EventName,
        message: item.Message,
        outputURL: item.OutputUrl,
        date: Date.now()
    }
    let lastEntry = this.state.receivedData[this.state.receivedData.length - 1]
    let timeDifference = dataset.date - lastEntry.date //time in ms
    let newDataArray = this.state.receivedData.concat(dataset);

    this.setState({
        receivedData: newDataArray,
        timeDifference: timeDifference
    });
}

edit: My personal implementation would be to actually split up the two concepts. I keep Date.now() and make a different function to actually build the array of time differences. Never know if you will need Date.now() later on, and it just makes more sense to have a timestamp in its entirety in your data. You don't need to add the item immediately. You can concat it later. I use object destructuring to make the assignment cleaning as 2 one-liners.

deploymentEventMessageReceived = (item) => {
  let { UtcNowPrettyText, EventName, Message, OutputUrl } = item
  let dataset = { UtcNowPrettyText, EventName, Message, OutputUrl, Date: Date.now() }
  this.setState({receivedData: this.state.receivedData.concat(dataset)})
}

buildTimeDifferences = (entries) => {
  let newArr = []
  for (let i = 0; i < entries.length; i++) {
    if (i !== entries.length - 1) {
      newArr.push(entries[i + 1].Date - entries[i].Date)
    }
  }
  return newArr
}


d = [{Date: 1},{ Date: 2}, {Date: 4}, {Date: 7}]
console.log(buildTimeDifferences(d))

Upvotes: 1

Related Questions