demo D22
Dates, times and zones in React
The same instant in four time zones
timeZone
This grid shows the same instant rendered in four different time zones at once. It lets each reader see the clock time that makes sense for them from one stored value, so a timestamp never means the wrong moment for someone in another place.
This is the React version. The grid mounts through the createLatticeGrid adapter, which takes its configuration as ordinary props and hands back the live grid through a ref. The grid below is the same one every other tab runs.
The configuration
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">
<div id="grid"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { createGrid } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/react.esm.min.js';
const LatticeGrid = createLatticeGrid({ React, createGrid });
// An instant type that keeps the zone: it stores the ISO string with its Z and
// compares on the parsed moment, so one field reads as the same instant for
// every viewer, shown in whichever zone each column names.
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 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' },
},
];
const rows = [/* nodes, each with a lastSeen instant */];
function App() {
return (
<LatticeGrid
rowKey="id"
toolPanel={{ side: 'left', panels: ['columns', 'filters', 'views', 'quick'],
actions: ['undo', 'redo', 'export', 'restore', 'maximise'], exportName: 'lattice-demo' }}
dataTypes={{ instant }}
columns={columns}
rows={rows}
style={{ height: '540px' }}
/>
);
}
createRoot(document.getElementById('grid')).render(<App />);
</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 with the grid’s timeZone setting: name an IANA zone and every date and timestamp in the grid reads in it, independent of the browser’s local zone. A timestamp column can also pin its own display zone with typeOptions.timeZone, so one grid can show the same instant in several zones side by side. 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. A timestamp column with no zone of its own takes the grid’s zone, and a grid with none takes the viewer’s local zone.
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 timestamp 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 grid to an IANA zone name, such as 'Europe/London' or 'Asia/Singapore', to show every date in that zone. To pin one timestamp column to a different zone, set typeOptions: { timeZone: 'Asia/Tokyo' } on it. Lattice Grid formats every value 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.