Lattice Grid Buy a licence

demo D23

Durations: JavaScript Data Grid Demo

Elapsed time that sorts numerically and reads as 3h 12m

type: 'duration'

This grid holds elapsed time that reads as '3h 12m' but sorts by actual length, so '1h 5m' comes before '10h 0m'. It fixes the trap of storing durations as text, giving you readable cells and correct ordering at once.

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.103.2/lattice-grid.min.css">
<script src="https://cdn.latticegrid.dev/lattice-grid@1.103.2/lattice-grid.min.js"></script>

<div id="grid" style="height: 540px"></div>

<script>
  const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
    rowKey: 'id',
    toolPanel: {
      side: 'left',
      panels: ['columns', 'filters', 'views', 'quick'],
      actions: ['undo', 'redo', 'export', 'restore', 'maximise'],
      exportName: 'lattice-demo',
    },
    columns: [
      { field: 'pipeline', title: 'Pipeline', filter: { type: 'set' }, layout: { width: 130, pin: 'start' } },
      { field: 'stage', title: 'Stage', filter: { type: 'set' }, layout: { width: 130 } },
      {
        field: 'outcome', title: 'Outcome', filter: { type: 'set' }, layout: { width: 120 },
        cell: { decoration: 'pill', variant: { map: { ok: 'success', retried: 'warning', failed: 'danger' } } },
      },
      // Milliseconds in, "3h 12m" out. The value stays a number, so the sort
      // is numeric, the range filter takes numbers and the total is a sum.
      { field: 'elapsed', title: 'Elapsed', type: 'duration', layout: { width: 140 }, total: 'sum' },
      { field: 'queued', title: 'Queued', type: 'duration', layout: { width: 140 }, total: 'sum' },
      { field: 'cpu', title: 'CPU time', type: 'duration', layout: { width: 140 }, total: 'sum' },
      {
        field: 'elapsedText', title: 'Elapsed, as text', type: 'text', layout: { width: 170 },
        // The same elapsed time as a person would have typed it. Sort this
        // column and then the one three to its left: this is the case the
        // type exists for.
        filter: { type: 'text' },
      },
      {
        id: 'share', title: 'CPU / elapsed', type: 'number', layout: { width: 150 },
        format: { style: 'percent', decimals: 0 },
        value: { deps: ['elapsed', 'cpu'], pure: true, compute: (d) => (d.elapsed ? d.cpu / d.elapsed : null) },
      },
      { field: 'records', title: 'Records', type: 'number', layout: { width: 130 }, format: { notation: 'compact' }, total: 'sum' },
    ],
    rows,  // pipeline runs, durations stored in milliseconds
  });
</script>

Formatting and sorting elapsed time correctly

Elapsed time is a poor fit for the number or date types: a raw second count is unreadable in a cell, and a formatted string like “3h 12m” sorts alphabetically rather than by duration, so “1h 5m” ends up after “10h 0m”. Lattice Grid’s type: 'duration' column stores the underlying value as seconds (or milliseconds, if you prefer) and keeps the comparator numeric while the renderer shows the short form a person actually reads, so a column of build times, session lengths or SLA countdowns sorts by true elapsed time even though every cell displays as hours and minutes rather than a number. A developer reaches for this type wherever a JavaScript data grid needs to show a span rather than a point: task duration, video length, uptime, time-to-resolution. Because the comparator works on the stored numeric value rather than the rendered string, sorting a column of durations costs the same as sorting any other numeric column, with no string-parsing step inserted per row, and it stays correct at any row count the grid virtualises.

The renderer also accepts a threshold so unusually long or short durations can carry a variant, letting a duration column double as an at-a-glance SLA indicator without a separate formatting rule.

How do you sort a duration column correctly in a data grid?

Store the duration as a plain number of seconds or milliseconds and let the grid’s type: 'duration' comparator sort on that value, rather than sorting the formatted string. Sorting the display text (“3h 12m”, “45m”) puts short-looking strings ahead of longer numeric durations; sorting the underlying seconds keeps the order numerically correct regardless of how compact the rendered label is.