Convert one moment across as many time zones as you need. The conversion uses the IANA database built into your browser, so daylight saving follows the rules in force on that date, not today's offset.
Asia/Jakarta Thu, 10 Sep 2026, 15:00 WIB UTC+7
Europe/Berlin Thu, 10 Sep 2026, 10:00 CEST UTC+2
America/New_York Thu, 10 Sep 2026, 04:00 EDT UTC-4
UTC Thu, 10 Sep 2026, 08:00 UTC UTC+0 Use the IANA zone name, never the
abbreviation. America/New_York and
EST are different things. EST is a fixed
offset of UTC-5, and New York uses it for only about
four months a year. The zone name carries that place's
full history of rules, including every time a government
moved the clocks, so a date in July and a date in
January convert differently and both are right.
Abbreviations are also ambiguous. CST is US Central, China Standard and Cuba Standard time; IST is India, Israel and Ireland. An abbreviation from another system gives you less information than you need to convert it.
One local hour never happens. In a zone that jumps at 02:00, 02:30 does not exist on that date, and a naive parser silently gives you 03:30 or 01:30. This tool shows a warning instead.
One local hour happens twice. 02:30 is two different instants an hour apart, and the local time alone does not say which one is meant. The tool warns you and shows the later one.
Scheduled jobs, billing periods and anything that logs local time. A nightly task at 02:15 runs twice or not at all, once a year, and the bug is hard to reproduce on any other night.
Store UTC. Keep the zone in its own column when the wall-clock time matters, and convert only at the edge where a human reads it.
// Formatting an instant in a zone: built in, no library needed
const when = new Date("2026-09-10T08:00:00Z");
console.log(new Intl.DateTimeFormat("en-GB", {
timeZone: "Asia/Jakarta",
dateStyle: "medium",
timeStyle: "short",
}).format(when));
// The current zone
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
// Going the other way, local wall-clock time to an instant, is the
// hard direction. Temporal makes it explicit:
// Temporal.ZonedDateTime.from("2026-09-10T15:00[Asia/Jakarta]")
// Until it ships everywhere, use a library:
// npm i date-fns-tz
const { fromZonedTime } = require("date-fns-tz");
console.log(fromZonedTime("2026-09-10 15:00", "Asia/Jakarta").toISOString()); A Date holds a single instant and displays it with the host's local offset. It has no concept of a named zone, which is why converting into one needs Intl or a library.
from datetime import datetime
from zoneinfo import ZoneInfo # standard library since 3.9
jakarta = ZoneInfo("Asia/Jakarta")
berlin = ZoneInfo("Europe/Berlin")
local = datetime(2026, 9, 10, 15, 0, tzinfo=jakarta)
print(local.astimezone(berlin))
print(local.astimezone(ZoneInfo("UTC")))
# Always aware, never naive, for anything that crosses a boundary
now = datetime.now(tz=ZoneInfo("UTC"))
# The ambiguous hour in autumn: fold picks which one you mean
ambiguous = datetime(2026, 11, 1, 1, 30, tzinfo=ZoneInfo("America/New_York"))
print(ambiguous.utcoffset()) # the first 01:30
print(ambiguous.replace(fold=1).utcoffset()) # the second -- PostgreSQL: timestamptz stores an instant, timestamp stores wall-clock text
CREATE TABLE events (
id bigserial PRIMARY KEY,
starts_at timestamptz NOT NULL, -- what you almost always want
zone text NOT NULL -- keep it when local time matters
);
SELECT starts_at AT TIME ZONE 'Asia/Jakarta' FROM events;
-- MySQL: TIMESTAMP converts to UTC on write and back on read;
-- DATETIME stores exactly what you gave it with no zone at all.
-- Mixing the two in one schema is a reliable source of confusion. Store UTC, and keep the IANA zone in its own column whenever the local wall-clock time is part of the meaning. For example, a meeting at 09:00 Jakarta time is a different fact from the instant it currently falls on. If the government changes the offset before the meeting, the instant should move and the local time should not, and a UTC value alone cannot do that.
Keep tzdata current on every server. The tz database is maintained by volunteers and updated several times a year, because governments set time zones and change them. Egypt brought DST back in 2023 after years without it, and Lebanon reversed a DST decision mid-transition the same year, leaving phones an hour apart within one country.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
Yes. Conversion uses the IANA time zone database in your browser, so it applies the rules in force on that date rather than today's offset. For example, 15 January and 15 July in Berlin convert with different offsets, and both are right.
EST is a fixed offset of UTC-5, and New York is off it for about eight months of the year. An IANA zone name carries the full history of when the rules changed; an abbreviation carries none of it, and several are ambiguous. CST alone means three different things.
One local hour is skipped in spring and one repeats in autumn. A time inside the skipped hour does not exist, and one inside the repeated hour is ambiguous. The tool shows a warning for both, and for the repeated hour it uses the later instant.
Yes. Type an IANA name such as Europe/Madrid into Add a zone and click Add. Every zone converts together, which helps when you need a meeting slot that works in Jakarta, Berlin and San Francisco at once. Reset goes back to the default list.
Store UTC, with a separate column for the IANA zone if the local wall-clock time matters. A local time stored without its zone loses information you cannot reconstruct, and the repeated hour each autumn is where that shows up first.
For epoch values, the Unix timestamp converter goes both ways, and the date converter reformats a date string. If you are scheduling something, remember cron runs in the server's zone: the cron generator explains the expression.