Time zones
Time scale
One trading session shown in UTC, New York, Berlin, or Tokyo time.
Interactive example — scroll, zoom, and hover the chart.
Code
// Lightweight Charts™ Example: Time zones
// https://tradingview.github.io/lightweight-charts/examples/time-scale/time-zones
const container = document.getElementById('container');
// The chart takes the space above the buttons, which are added further down.
container.style.display = 'flex';
container.style.flexDirection = 'column';
const chartElement = document.createElement('div');
chartElement.style.flex = '1';
chartElement.style.minHeight = '0';
container.appendChild(chartElement);
/** @type {import('lightweight-charts').IChartApi} */
const chart = createChart(chartElement, chartOptions);
const series = chart.addSeries(CandlestickSeries, {
upColor: '#26a69a',
downColor: '#ef5350',
borderVisible: false,
wickUpColor: '#26a69a',
wickDownColor: '#ef5350',
});
// The data keeps its UTC timestamps; each time zone gets a shifted copy.
const utcData = generateBars();
// Returns a function that moves a UTC timestamp so that the chart, which shows
// every time in UTC, shows the local time of `timeZone` instead.
function createTimeToTz(timeZone) {
// Create the format once and reuse it: creating one is slow.
const format = new Intl.DateTimeFormat('en-US', {
timeZone,
hourCycle: 'h23',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
});
return originalTime => {
const parts = {};
for (const { type, value } of format.formatToParts(new Date(originalTime * 1000))) {
parts[type] = Number(value);
}
return Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second) / 1000;
};
}
function setTimeZone(timeZone) {
const timeToTz = createTimeToTz(timeZone);
series.setData(utcData.map(bar => ({ ...bar, time: timeToTz(bar.time) })));
}
const timeZones = ['UTC', 'America/New_York', 'Europe/Berlin', 'Asia/Tokyo'];
timeZones.forEach(timeZone => {
const button = document.createElement('button');
button.innerText = timeZone;
button.addEventListener('click', () => setTimeZone(timeZone));
buttonsContainer.appendChild(button);
});
container.appendChild(buttonsContainer);
// Start in New York, where the session runs from 9:30 to 16:00.
setTimeZone('America/New_York');
chart.timeScale().fitContent();
// Sample data: 30-minute bars of a US stock session, 14:30 to 21:00 UTC, on
// five weekdays. A seeded random walk, so the chart looks the same on every load.
function generateBars() {
let seed = 23;
const random = () => (seed = (seed * 16807) % 2147483647) / 2147483647;
const bars = [];
let close = 180;
for (let day = 8; day <= 12; day++) {
for (let minutes = 14 * 60 + 30; minutes < 21 * 60; minutes += 30) {
const open = close;
close = open + (random() - 0.5) * 2;
const high = Math.max(open, close) + random();
const low = Math.min(open, close) - random();
const time = Date.UTC(2024, 0, day, 0, minutes) / 1000;
bars.push({ time, open, high, low, close });
}
}
return bars;
}
The code expects the library’s exports, such as createChart, to be imported and a div with the id container on the page. Copy as HTML gives a page that runs on its own.
How it works
The chart shows every time in UTC and has no time zone option. To show another time zone, shift the timestamps so that their UTC time reads as the local time of that zone. The bars here are a US stock session, from 14:30 to 21:00 UTC, which is 9:30 to 16:00 in New York.
createTimeToTzcreates anIntl.DateTimeFormatfor the time zone once, and returns a function that reads the local date and time of a timestamp with it, then builds a UTC timestamp from them withDate.UTC.- The buttons call
setTimeZone. It shifts a copy of the data with that function and passes the copy tosetData. The original UTC data stays unchanged, so the zone can be switched again.
These lines are highlighted in the code. generateBars only makes sample data. Replace it with your own.
Tips
Intl.DateTimeFormatknows daylight saving time, so each timestamp gets the offset that applied on its own date.- With the format created once, 100,000 points take about 0.4 seconds in our tests. For larger data sets, see the
tzdataapproach in Time zones. - Shift the data you pass to
updatetoo, or new bars land in the wrong place.
Resources
- Time zones
timeScale.timeVisible- Related examples: Custom date format, Custom locale