demo D22
Dates, times and zones
The same instant in four time zones
timeZone
The configuration
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.css">
<script src="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.js"></script>
<div id="grid" style="height: 540px"></div>
<script>
// A type is a map entry. `instant` exists because the shipped `datetime`
// drops the zone: it stores the ISO string with its Z and compares on the
// parsed epoch, so the same field means one moment to every reader.
const instant = {
base: 'text',
storage: 'dictionary',
compare: (a, b) => {
const x = a == null ? NaN : Date.parse(String(a));
const y = b == null ? NaN : Date.parse(String(b));
if (Number.isNaN(x)) return Number.isNaN(y) ? 0 : 1;
if (Number.isNaN(y)) return -1;
return x - y;
},
defaults: { filter: 'text', align: 'start' },
};
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',
},
dataTypes: { instant },
columns: [
{ field: 'hostname', title: 'Hostname', layout: { width: 260, pin: 'start' } },
{ field: 'lastSeen', id: 'raw', title: 'Stored', type: 'instant', layout: { width: 210 } },
{ field: 'lastSeen', id: 'utc', title: 'UTC', type: 'instant', layout: { width: 160 }, format: { type: 'date', timeZone: 'UTC', pattern: 'yyyy-MM-dd HH:mm' } },
{ field: 'lastSeen', id: 'lon', title: 'Europe/London', type: 'instant', layout: { width: 170 }, format: { type: 'date', timeZone: 'Europe/London', pattern: 'yyyy-MM-dd HH:mm' } },
{ field: 'lastSeen', id: 'nyc', title: 'America/New_York', type: 'instant', layout: { width: 180 }, format: { type: 'date', timeZone: 'America/New_York', pattern: 'yyyy-MM-dd HH:mm' } },
{ field: 'lastSeen', id: 'tyo', title: 'Asia/Tokyo', type: 'instant', layout: { width: 160 }, format: { type: 'date', timeZone: 'Asia/Tokyo', pattern: 'yyyy-MM-dd HH:mm' } },
{
field: 'lastSeen', id: 'rel', title: 'Relative', type: 'instant', layout: { width: 150 },
// Falls back to an absolute date once the gap passes the threshold,
// which is what stops a list of old rows reading "412 days ago".
format: { type: 'date', relative: { threshold: 7 } },
},
{
field: 'commissioned', title: 'Commissioned', type: 'dateString', layout: { width: 160 },
// A day, not an instant. It has no zone to convert and should not
// get one: 4 March is 4 March in Tokyo too.
format: { type: 'date', dateStyle: 'medium' },
},
],
rows, // nodes, each with a lastSeen instant
});
</script>
Rendering the same instant correctly across time zones
A date value stored in a row is a single instant, but a reader in London and a reader in Singapore need to see two different clock times for it. Lattice Grid handles this at the column level with the timeZone option: set it on a date or datetime column and every cell formats its value against the named zone, independent of the browser’s local zone. This matters for a JavaScript data grid used by a distributed team, an operations dashboard tracking events across regions, or an audit log where the recorded instant must read out consistently regardless of viewer. Columns without timeZone set fall back to the viewer’s local zone, so one grid can mix a local-time column with fixed-zone columns side by side, each formatting independently from the same underlying instant.
Formatting runs through Intl.DateTimeFormat, so zone names follow the IANA database rather than fixed UTC offsets, keeping daylight saving transitions correct without the grid tracking them itself. The formatter for a given zone and locale pairing is built once per column and reused across every row, so scrolling a long list of timestamped rows does not repeat that setup cost per cell. Sorting and filtering compare the underlying instant, not the formatted string, so a timeZone column sorts correctly even when the displayed hour rolls past midnight differently between zones.
How do you display a date column in a fixed time zone in a data grid?
Set timeZone on the column definition to an IANA zone name, such as 'Europe/London' or 'Asia/Singapore'. Lattice Grid formats every value in that column against the named zone using Intl.DateTimeFormat, independent of the viewer’s local zone, while sorting and filtering continue to operate on the underlying instant rather than the formatted display string.