Skip to main content
Version: 7.1.2

Nanosecond timestamps

Nanosecond and microsecond timestamps are unsupported out of the box, due to the numbers generally being too large and having too many decimals for LightningChart JS high precision axis (or normal JavaScript numbers for that matter). However, they can be realized with so called "origin shift" approach.

In practice this means:

  1. Subtracting all timestamps by the value of first displayed timestamp rounded to closest date, midnight (so counting starts from near 0).
  2. Informing the charts about the shift using setDateOrigin method.

Additionally, nanosecond timestamps should be converted to milliseconds (divided by 1_000_000).

tip

This data preparation can either be done in backend or in the frontend. If done in frontend, then most likely you need to transfer the timestamp data as BigInt64Array because primitive JavaScript numbers can't accurately store nanosecond timestamps.

Example code:

// data { x: BigInt64Array, y: Float64Array }
const chart = lc.ChartXY({
defaultAxisX: {
type: 'linear-highPrecision',
},
})
const series = chart.addPointLineAreaSeries({ dataPattern: 'ProgressiveX' })
.setAreaFillStyle(emptyFill)
.setStrokeStyle(emptyLine)
// LCJS can't directly consume BigInt64Array
// shift bigint64 data to start from near 0 in order to store it in Float64Array without losing nanosecond precision
const xsShifted = new Float64Array(count)
const shiftDate = new Date(Number(data.x[0]) / 1_000_000)
// shift position should be beginning of date (00:00:00.000)
shiftDate.setUTCHours(0, 0, 0, 0)
const shiftOrigin = shiftDate.getTime() * 1_000_000
const shiftOriginNanos = BigInt(shiftOrigin) * BigInt(1_000_000)
for (let i = 0; i < count; i++) {
xsShifted[i] = Number(data.x[i] - shiftOriginNanos) / 1_000_000
}
series.appendSamples({ xValues: xsShifted, yValues: data.y })
chart.axisX.setTickStrategy(AxisTickStrategies.DateTime, (strategy) => strategy
.setDateOrigin(shiftDate)
)

At these extreme zoom in ranges, there are some limitations in supported series configurations.

  • Area fill not supported.
  • Thick line series not supported (should use -1 as stroke thickness)

Achievable zoom in capability depends on the total time range of loaded data set. For 1 week of data, it is as in above demonstration - min interval ~= 250 nanoseconds. If longer time period is loaded, then zoom limits kick in earlier.

Here's a rough look up table for convenience:

time rangemin interval
8 hours10 nanoseconds
1 week250 nanoseconds
1 year12 microseconds

Minimum interval refers to value range on time axis, meaning perceivable minimum time step is considerably smaller than this. Like in above demonstration, you can clearly see steps of 1 nanosecond.