@geoapify/iana-timezone-metadata
v1.0.0
Published
Compact IANA timezone metadata, aliases, UTC offsets, DST states, transitions, and country lookups.
Maintainers
Readme
IANA Timezone Metadata for TypeScript
@geoapify/iana-timezone-metadata
A dependency-free TypeScript and JavaScript library for fast IANA timezone lookup. Get canonical timezone identifiers and aliases, UTC offsets, DST states and transitions, abbreviations, country mappings, and bundled tzdb version information.
Features
- canonical IANA timezone identifiers and aliases
- standard, daylight-saving, and exceptional timezone states
- formatted UTC offsets, offset seconds, and abbreviations
- timezone state lookup at a specific instant
- next-transition and transition-range lookup
- canonical timezones associated with ISO country codes
- bundled tzdb version, reference year, and supported transition range
- immutable results and zero runtime dependencies
Installation
npm install @geoapify/iana-timezone-metadataThe package is ESM-only, includes TypeScript declarations, supports Node.js 18 and later, and can be used by browser applications through an ESM-compatible bundler.
Quick start
import {
getNextTransition,
getTimezone,
getTimezoneState,
} from "@geoapify/iana-timezone-metadata";
const timezone = getTimezone("Europe/Nicosia");
console.log(timezone?.id);
// "Asia/Nicosia"
console.log(timezone?.standard);
// {
// type: "standard",
// utcOffset: "+02:00",
// offsetSeconds: 7200,
// abbreviation: "EET",
// daylightSavingOffsetSeconds: 0
// }
const state = getTimezoneState(
"Asia/Nicosia",
new Date("2026-08-03T12:00:00Z"),
);
console.log(state?.abbreviation);
// "EEST"
const nextTransition = getNextTransition(
"Asia/Nicosia",
new Date("2026-08-03T12:00:00Z"),
);
console.log(nextTransition?.at);
// "2026-10-25T01:00:00Z"API reference
| Function | Description |
|---|---|
| getTimezone() | Returns canonical TimezoneInfo metadata for an identifier or alias. |
| getTimezoneState() | Returns the TimezoneState active at a TimezoneInstant. |
| getNextTransition() | Returns the next TimezoneTransition after an instant. |
| getTransitions() | Returns TimezoneTransition objects within a TransitionRange. |
| getTimezonesForCountry() | Returns canonical TimezoneInfo objects associated with an ISO country code. |
| resolveTimezone() | Resolves a canonical identifier or alias to its canonical identifier. |
| isTimezone() | Reports whether an identifier is a known canonical timezone or alias. |
| listTimezones() | Lists TimezoneInfo metadata for every canonical timezone. |
| listTimezoneIds() | Lists canonical identifiers, optionally including aliases through ListTimezoneIdOptions. |
The databaseInfo constant exposes the bundled
DatabaseInfo, including the tzdb version, reference
year, and supported transition range.
getTimezone()
Returns reference-year metadata for a canonical IANA identifier or alias.
getTimezone(id: string): TimezoneInfo | undefinedParameters
| Name | Type | Description |
|---|---|---|
| id | string | Canonical IANA timezone identifier or known alias. |
Returns
A frozen TimezoneInfo object, or undefined when the
identifier is unknown. When an alias is supplied, the returned object's id is
canonical.
Example
const canonical = getTimezone("Asia/Nicosia");
const alias = getTimezone("Europe/Nicosia");
console.log(alias?.id);
// "Asia/Nicosia"
console.log(alias === canonical);
// truegetTimezoneState()
Returns the state active in a timezone at a particular instant.
getTimezoneState(
id: string,
at?: TimezoneInstant,
): TimezoneState | undefinedParameters
| Name | Type | Description |
|---|---|---|
| id | string | Canonical timezone identifier or alias. |
| at | TimezoneInstant | Date or Unix milliseconds. Defaults to the current instant. |
Returns
The frozen TimezoneState active at at, or undefined for
an unknown identifier.
Throws
RangeError when at is invalid or outside
databaseInfo.transitionRange.
Example
const state = getTimezoneState(
"Asia/Nicosia",
Date.parse("2026-08-03T12:00:00Z"),
);
console.log(state);
// {
// type: "daylightSaving",
// utcOffset: "+03:00",
// offsetSeconds: 10800,
// abbreviation: "EEST",
// daylightSavingOffsetSeconds: 3600
// }getNextTransition()
Returns the first timezone transition strictly after an instant.
getNextTransition(
id: string,
after?: TimezoneInstant,
): TimezoneTransition | null | undefinedParameters
| Name | Type | Description |
|---|---|---|
| id | string | Canonical timezone identifier or alias. |
| after | TimezoneInstant | Date or Unix milliseconds. Defaults to the current instant. |
Returns
- a
TimezoneTransitionwhen another transition exists; nullfor a known timezone with no later transition in the supported range;undefinedfor an unknown identifier.
Throws
RangeError when after is invalid or outside the supported transition range.
Example
const transition = getNextTransition(
"Asia/Nicosia",
Date.parse("2026-08-03T00:00:00Z"),
);
console.log(transition);
// {
// at: "2026-10-25T01:00:00Z",
// before: { type: "daylightSaving", abbreviation: "EEST", ... },
// after: { type: "standard", abbreviation: "EET", ... },
// offsetChangeSeconds: -3600,
// kind: "daylight-end"
// }getTransitions()
Returns all timezone transitions in a half-open interval: from is inclusive
and to is exclusive.
getTransitions(
id: string,
range: TransitionRange,
): readonly TimezoneTransition[] | undefinedParameters
| Name | Type | Description |
|---|---|---|
| id | string | Canonical timezone identifier or alias. |
| range | TransitionRange | Inclusive start and exclusive end of the query. |
Returns
A frozen transition array, an empty array when the known timezone has no
transitions in the interval, or undefined for an unknown identifier.
Throws
RangeError when the range is invalid or extends outside the supported
transition range.
Example
const transitions = getTransitions("Asia/Nicosia", {
from: Date.UTC(2026, 0, 1),
to: Date.UTC(2027, 0, 1),
});
console.log(transitions?.map(({ at, kind }) => ({ at, kind })));
// [
// { at: "2026-03-29T01:00:00Z", kind: "daylight-start" },
// { at: "2026-10-25T01:00:00Z", kind: "daylight-end" }
// ]getTimezonesForCountry()
Returns canonical timezone metadata associated with an ISO country code.
getTimezonesForCountry(countryCode: string): readonly TimezoneInfo[]Parameters
| Name | Type | Description |
|---|---|---|
| countryCode | string | Case-insensitive ISO 3166-1 alpha-2 country code. |
Returns
A frozen array of canonical TimezoneInfo objects. An unknown
country code returns an empty array. Associations come from IANA's zone tables.
Example
const timezones = getTimezonesForCountry("cy");
console.log(timezones.map(({ id }) => id));
// ["Asia/Famagusta", "Asia/Nicosia"]resolveTimezone()
Resolves a canonical timezone identifier or alias to its canonical identifier.
resolveTimezone(id: string): string | undefinedParameters
| Name | Type | Description |
|---|---|---|
| id | string | Canonical timezone identifier or alias. |
Returns
The canonical identifier, or undefined when id is unknown.
Example
resolveTimezone("Europe/Nicosia"); // "Asia/Nicosia"
resolveTimezone("Invalid/Zone"); // undefinedisTimezone()
Reports whether a string is a known canonical timezone identifier or alias.
isTimezone(id: string): booleanParameters
| Name | Type | Description |
|---|---|---|
| id | string | Canonical timezone identifier or alias. |
Returns
true when id is a known canonical identifier or alias; otherwise false.
Example
isTimezone("Asia/Nicosia"); // true
isTimezone("Europe/Nicosia"); // true
isTimezone("Invalid/Zone"); // falselistTimezones()
Lists metadata for every canonical timezone.
listTimezones(): readonly TimezoneInfo[]Returns
The returned array and its timezone objects are frozen. Aliases do not create duplicate entries.
listTimezoneIds()
Lists sorted timezone identifier strings.
listTimezoneIds(
options?: ListTimezoneIdOptions,
): readonly string[]Parameters
| Name | Type | Description |
|---|---|---|
| options.includeAliases | boolean | Include aliases as well as canonical identifiers. Defaults to false. |
Returns
A frozen, sorted array of identifier strings.
Example
const canonicalIds = listTimezoneIds();
const allIds = listTimezoneIds({ includeAliases: true });databaseInfo
Describes the bundled tzdb release and the generated data range.
const databaseInfo: DatabaseInfoconsole.log(databaseInfo);
// {
// tzdbVersion: "2026c",
// referenceYear: 2026,
// transitionRange: {
// from: "2025-01-01T00:00:00Z",
// until: "2032-01-01T00:00:00Z"
// }
// }The transition range is half-open: from is supported and until is not.
Types
TimezoneInfo
Reference-year metadata for one canonical timezone.
interface TimezoneInfo {
readonly id: string;
readonly aliases: readonly string[];
readonly countryCodes: readonly string[];
readonly location?: TimezoneLocation;
readonly referenceYear: number;
readonly standard: TimezoneState;
readonly otherStates: readonly TimezoneState[];
readonly hasDaylightSavingTime: boolean;
readonly hasTransitions: boolean;
}| Property | Description |
|---|---|
| id | Canonical IANA timezone identifier. |
| aliases | Other identifiers resolving to this timezone. |
| countryCodes | Associated ISO country codes from IANA zone tables. |
| location | Representative location, not boundary geometry. |
| referenceYear | Calendar year used to produce standard, otherStates, and the boolean flags. |
| standard | Primary standard state, selected as the standard state active for the largest portion of the reference year. |
| otherStates | Other states observed during the reference year. |
| hasDaylightSavingTime | Whether a daylight-saving state occurs during the reference year. |
| hasTransitions | Whether any state transition occurs during the reference year. |
TimezoneState
One distinct offset and abbreviation state.
interface TimezoneState {
readonly type: TimezoneStateType;
readonly utcOffset: string;
readonly offsetSeconds: number;
readonly abbreviation: string;
readonly daylightSavingOffsetSeconds: number;
}| Property | Description |
|---|---|
| type | State classification. |
| utcOffset | Formatted offset such as "+05:30" or "-04:00". |
| offsetSeconds | Signed offset east of UTC in seconds. |
| abbreviation | tzdb abbreviation such as EET or EEST. |
| daylightSavingOffsetSeconds | Adjustment relative to standard time. It may be negative or non-hourly. |
TimezoneStateType
type TimezoneStateType = "standard" | "daylightSaving" | "other";other is reserved for states that cannot be accurately classified as standard
or daylight-saving time.
TimezoneTransition
An exact change from one complete timezone state to another.
interface TimezoneTransition {
readonly at: string;
readonly before: TimezoneState;
readonly after: TimezoneState;
readonly offsetChangeSeconds: number;
readonly kind: TimezoneTransitionKind;
}| Property | Description |
|---|---|
| at | Transition instant as a UTC ISO 8601 string. |
| before | State immediately before the transition. |
| after | State at and immediately after the transition. |
| offsetChangeSeconds | after.offsetSeconds - before.offsetSeconds. |
| kind | Classification of the transition. |
TimezoneTransitionKind
type TimezoneTransitionKind =
| "daylight-start"
| "daylight-end"
| "offset-change"
| "designation-change";An offset-change is not classified as DST. A designation-change changes an
abbreviation or state designation without moving the clock.
TimezoneLocation
interface TimezoneLocation {
readonly latitude: number;
readonly longitude: number;
readonly comments?: string;
}The coordinates identify IANA's representative location for a timezone. They cannot be used to determine which timezone contains an arbitrary coordinate.
TimezoneInstant
type TimezoneInstant = Date | number;Numbers are Unix timestamps in milliseconds, matching JavaScript Date.
TransitionRange
interface TransitionRange {
readonly from: TimezoneInstant;
readonly to: TimezoneInstant;
}from is inclusive and to is exclusive.
ListTimezoneIdOptions
interface ListTimezoneIdOptions {
readonly includeAliases?: boolean;
}DatabaseInfo type
interface DatabaseInfo {
readonly tzdbVersion: string;
readonly referenceYear: number;
readonly transitionRange: {
readonly from: string;
readonly until: string;
};
}Code samples
Get IANA timezone metadata
Read the standard state, other observed states, country associations, and aliases for a timezone:
import { getTimezone } from "@geoapify/iana-timezone-metadata";
const timezone = getTimezone("Asia/Nicosia");
if (!timezone) {
throw new Error("Unknown timezone");
}
console.log({
standardOffset: timezone.standard.utcOffset,
otherStates: timezone.otherStates,
usesDaylightSavingTime: timezone.hasDaylightSavingTime,
countryCodes: timezone.countryCodes,
aliases: timezone.aliases,
});Get UTC offset and DST state for a date
Determine which offset and abbreviation apply at an exact point in time:
import { getTimezoneState } from "@geoapify/iana-timezone-metadata";
const state = getTimezoneState(
"America/New_York",
new Date("2026-07-01T12:00:00Z"),
);
console.log({
offset: state?.utcOffset,
abbreviation: state?.abbreviation,
isDaylightSavingTime: state?.type === "daylightSaving",
});
// { offset: "-04:00", abbreviation: "EDT", isDaylightSavingTime: true }List timezone and DST transitions
Build a schedule of clock changes within a half-open date range:
import { getTransitions } from "@geoapify/iana-timezone-metadata";
const transitions = getTransitions("Europe/Berlin", {
from: Date.UTC(2026, 0, 1),
to: Date.UTC(2027, 0, 1),
});
const schedule = transitions?.map((transition) => ({
at: transition.at,
from: transition.before.utcOffset,
to: transition.after.utcOffset,
kind: transition.kind,
}));
console.log(schedule);List IANA timezones by country
Country codes are case-insensitive ISO 3166-1 alpha-2 codes:
import { getTimezonesForCountry } from "@geoapify/iana-timezone-metadata";
const timezones = getTimezonesForCountry("us");
console.log(timezones.map(({ id }) => id));Resolve latitude and longitude to an IANA timezone
This package does not include timezone boundary geometry, so it cannot resolve
latitude and longitude directly. First obtain an IANA timezone identifier with
a geometry package or geocoding service, then pass that identifier to
getTimezone() and the transition APIs.
Server-side lookup with geo-tz
For a local lookup in a Node.js application,
geo-tz provides timezone boundary
data:
npm install geo-tzimport { find } from "geo-tz";
import { getTimezone } from "@geoapify/iana-timezone-metadata";
const timezoneIds = find(47.650499, -122.35007);
const timezoneId = timezoneIds[0];
const timezone = timezoneId ? getTimezone(timezoneId) : undefined;
console.log(timezone?.id);
// "America/Los_Angeles"find() returns an array because a coordinate can have multiple timezone
candidates near borders or in disputed areas. Decide how to handle every
candidate when that distinction matters to your application.
Get a timezone with Geoapify Reverse Geocoding
As an alternative, the
Geoapify Reverse Geocoding API
returns timezone information together with the address. Its timezone object
already includes the IANA identifier, standard and daylight-saving offsets,
and abbreviations. If those fields are sufficient, no additional timezone
lookup is necessary.
Use timezone.name with this package when you also need its normalized
metadata or transition APIs:
import { getTimezone } from "@geoapify/iana-timezone-metadata";
const params = new URLSearchParams({
lat: "47.650499",
lon: "-122.35007",
format: "json",
apiKey: "YOUR_GEOAPIFY_API_KEY",
});
const response = await fetch(
`https://api.geoapify.com/v1/geocode/reverse?${params}`,
);
if (!response.ok) {
throw new Error(`Reverse geocoding failed: ${response.status}`);
}
const data = await response.json();
const timezoneId = data.results[0]?.timezone?.name;
const timezone = timezoneId ? getTimezone(timezoneId) : undefined;
console.log(timezone?.id);
// "America/Los_Angeles"Get timezone metadata from browser geolocation
In a browser, combine the Geolocation API with reverse geocoding to return a
TimezoneInfo object for the user's current position:
import {
getTimezone,
type TimezoneInfo,
} from "@geoapify/iana-timezone-metadata";
function getCurrentPosition(): Promise<GeolocationPosition> {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject);
});
}
async function getCurrentTimezone(
geoapifyApiKey: string,
): Promise<TimezoneInfo | undefined> {
const { coords } = await getCurrentPosition();
const params = new URLSearchParams({
lat: String(coords.latitude),
lon: String(coords.longitude),
format: "json",
apiKey: geoapifyApiKey,
});
const response = await fetch(
`https://api.geoapify.com/v1/geocode/reverse?${params}`,
);
if (!response.ok) {
throw new Error(`Reverse geocoding failed: ${response.status}`);
}
const data = await response.json() as {
results?: Array<{ timezone?: { name?: string } }>;
};
const timezoneId = data.results?.[0]?.timezone?.name;
return timezoneId ? getTimezone(timezoneId) : undefined;
}
const timezone = await getCurrentTimezone("YOUR_GEOAPIFY_API_KEY");
console.log(timezone?.id);
console.log(timezone?.standard.utcOffset);Browser geolocation requires a secure context and the user's permission. When calling Geoapify directly from a browser, restrict the API key to your allowed origins.
Limitations
- The package does not perform coordinate-to-timezone lookup and contains no timezone boundary polygons.
- Locations are representative points supplied by IANA, not geographic coverage definitions.
- It does not provide localized display names or Windows timezone identifiers.
- Timezone abbreviations are not globally unique.
- Country associations come from IANA's zone tables and do not imply exact geographic coverage.
- Future transitions are predictions from the bundled tzdb release and can change when governments change their rules.
- State and transition queries are limited to
databaseInfo.transitionRange.
Data source and generation
The data is generated from the official
IANA Time Zone Database. Runtime results use
the bundled tzdb release and do not depend on the timezone database provided by
the host's JavaScript Intl implementation.
Two generated artifacts are maintained:
data/iana-tzdb.jsonis a readable representation of source-level zone eras, rules, links, leap seconds, countries, and IANA zone tables.src/generated/data.tsis the compact runtime artifact containing reference-year states and exact transitions.
The runtime transition range starts one year before the reference year and ends
after five future years. Generation requires the IANA zic compiler on PATH,
or its path can be supplied through TZDB_ZIC.
npm install
npm run generate -- --version 2026c --reference-year 2026
npm run check
npm run buildUse npm run generate without arguments to resolve IANA's current release and
the current UTC calendar year automatically.
License
MIT © Geoapify. See LICENSE.
