Always up to date time zones for time zone pickers, and the country of any time zone.
import { getTimeZones } from "@vvo/tzdb";
getTimeZones().map((timeZone) => timeZone.currentTimeFormat);
// [..., "-07:00 Pacific Time - Los Angeles, San Diego, San Jose, San Francisco", ...]- Every IANA time zone, grouped by country and clock, with major cities.
- Current offsets and abbreviations: PDT in summer, PST in winter.
- Every current and deprecated IANA name, so saved values always find their entry.
- Names in any language the browser supports.
- The country of a visitor's time zone, to guess where they are without an IP lookup.
- No dependencies, ESM and CommonJS, TypeScript types.
Every day, a GitHub workflow compiles the latest IANA tz database, takes city populations from GeoNames, tests the result and publishes a new version when something changed.
Current offsets come from the browser or Node.js at runtime. A site that never updates this package
still follows daylight saving changes, and agrees with the offsets Intl.DateTimeFormat gives the
rest of the app.
npm add @vvo/tzdbimport { getTimeZones } from "@vvo/tzdb";
const timeZones = getTimeZones();
// Saved values can be any IANA name, like "Asia/Calcutta" or "US/Pacific"
function findTimeZone(name) {
return timeZones.find((timeZone) => timeZone.group.includes(name));
}
function TimeZonePicker({ value, onChange }) {
const selected = findTimeZone(value ?? Intl.DateTimeFormat().resolvedOptions().timeZone);
return (
<select value={selected?.name} onChange={(event) => onChange(event.target.value)}>
{timeZones.map((timeZone) => (
<option key={timeZone.name} value={timeZone.name}>
{timeZone.currentTimeFormat}
</option>
))}
</select>
);
}Save name in the database: every Intl API and date library accepts it.
To search, match the query against the fields people type:
timeZones.filter((timeZone) =>
[timeZone.currentTimeFormat, timeZone.countryName, timeZone.abbreviation, ...timeZone.group]
.join(" ")
.toLowerCase()
.includes(query.toLowerCase()),
);import { getCountryCode } from "@vvo/tzdb";
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; // "Europe/Paris"
getCountryCode(timeZone); // "FR"
new Intl.DisplayNames(["en"], { type: "region" }).of("FR"); // "France"It knows every IANA name, including old ones browsers still return, like Asia/Calcutta. It weighs
4 kB and does not load the time zone list.
import {
getTimeZones,
getCountryCode,
rawTimeZones,
timeZonesNames,
abbreviations,
tzdbVersion,
} from "@vvo/tzdb";Returns time zones sorted by current offset:
{
name: "America/Los_Angeles",
alternativeName: "Pacific Time",
group: ["America/Los_Angeles", "US/Pacific", "PST8PDT"],
continentCode: "NA",
continentName: "North America",
countryName: "United States",
countryCode: "US",
mainCities: ["Los Angeles", "San Diego", "San Jose", "San Francisco"],
rawOffsetInMinutes: -480,
abbreviation: "PST",
dstAbbreviation: "PDT", // only for zones with daylight saving time
rawFormat: "-08:00 Pacific Time - Los Angeles, San Diego, San Jose, San Francisco",
currentTimeOffsetInMinutes: -420,
currentTimeFormat: "-07:00 Pacific Time - Los Angeles, San Diego, San Jose, San Francisco",
currentAbbreviation: "PDT",
}Options:
locale: translatesalternativeName,countryNameandcontinentName. With"fr", Los Angeles shows as "-07:00 heure du Pacifique nord-américain - Los Angeles, ...". City names stay as they are.includeUtc: addsEtc/UTC, whose group includesUTCandGMT.date: computes thecurrent*fields at this date instead of now, like the date of a meeting.includeGmtOffsets: adds the fixed offsetsEtc/GMT-14toEtc/GMT+12. As in POSIX, the sign is inverted:Etc/GMT+5is 5 hours behind UTC.
Zones the browser does not know yet are left out, since Intl could not format dates in them.
Runtimes without Intl time zone support get every zone at its standard offset.
The ISO 3166 country code of an IANA time zone
name, or undefined for names without a country like UTC.
The same list without the current* fields, sorted by standard offset.
Every IANA time zone name from zone.tab.
Long names mapped to abbreviations, like "Central European Summer Time": "CEST". Careful, CST
means Central Standard Time (-06:00), China Standard Time (+08:00) and Cuba Standard Time (-05:00).
The IANA tz database release behind the data, like "2026e".
| @vvo/tzdb | countries-and-timezones | |
|---|---|---|
| Data updates | Every day, automatically | By hand |
| Current offsets | From the browser, at runtime | Computed when the package was built |
| Abbreviations that follow DST | Yes | No |
| Translations | Any language the browser has | No |
| Country of a time zone | 4 kB | 9 kB |
| Picker list with cities and names | 17 kB | Not available |
Sizes are minified and gzipped. countries-and-timezones weighs 9 kB in total, without cities, display names or abbreviations.
Zones share an entry when they are in the same country and their clocks showed the same time for the past year and will for the next two. Detroit and New York had different rules a century ago, so IANA keeps both, but they share an entry today. Zones that just changed their rules, like Edmonton, keep their own entry for a year, while browsers catch up.
alternativeName is the English name from CLDR without "Standard",
"Daylight" or "Summer". When summer and winter names differ, like "Greenwich Mean Time" and "British
Summer Time", it is CLDR's generic name, "United Kingdom Time". Several countries share names like
"Eastern Time", so show countryName or mainCities next to it.
Abbreviations come from IANA. When IANA has none, like "+03", they come from abbreviations or
read "GMT+3".