Time zones without surprises — UTC, offsets and daylight saving time
The difference between a time zone and a UTC offset, why the gap between two cities changes during the year, and how to store and convert times safely.
By Felipe YamaokaPublished November 5, 20266 min read
The meeting that moved by itself
A team in São Paulo schedules a weekly call with a client in New York: 10:00 in São Paulo, 8:00 in New York. In July the client joins an hour late, and nobody changed the invite. In March the problem appears again, in the other direction. Nothing broke in the calendar. What changed was the clock in New York.
Time zones look simple until you need them to be correct on every date. This guide explains the vocabulary, why the difference between two cities is not constant, and the few rules that avoid most bugs in code.
UTC, offsets and time zones are different things
Three terms are often used as synonyms, and they are not:
- UTC (Coordinated Universal Time) is the reference clock. It never changes for daylight saving and is what servers, logs and timestamps should use.
- An offset is a fixed distance from UTC at a given moment, written as
UTC−3,-03:00orUTC+5:30. - A time zone is a region with a history of rules, identified by an IANA name such as
America/Sao_Paulo,America/New_YorkorEurope/London. The rules say which offset applies on each date.
The key idea: a time zone is not an offset. America/New_York is UTC−5 in January and UTC−4 in July. If you store "New York = −5", half of the year is wrong.
The IANA time zone database, also called tzdata, is maintained by volunteers and updated several times a year, because governments change their rules. Brazil, for example, abolished daylight saving time in 2019. Since then America/Sao_Paulo is UTC−3 all year, but a date from 2018 still uses the old rules. Browsers, operating systems and programming languages ship a copy of that database, which is why you should always refer to zones by their IANA names, not by abbreviations.
Why abbreviations are a trap
EST, CST and IST look convenient but are ambiguous. CST can mean Central Standard Time in the United States (UTC−6), China Standard Time (UTC+8) or Cuba Standard Time (UTC−5). IST is used in India, Ireland and Israel. And an abbreviation describes only one season: writing "9:00 EST" for a date in July is simply wrong, since New York is on EDT then.
Use the IANA name in data and code, and show abbreviations only as a label for people, if at all.
Daylight saving changes the gap between cities
Daylight saving time (DST) moves clocks forward in spring and back in autumn, but countries do it on different dates, and many do not do it at all. The result is that the difference between two cities changes during the year.
Some real numbers for 2026:
- São Paulo and New York: 2 hours apart in January, 1 hour apart in July, because only New York moves its clocks.
- São Paulo and London: 3 hours in January, 4 hours in July.
- New York and London: usually 5 hours, but only 4 hours between 8 and 29 March and between 25 October and 1 November, because the United States and the United Kingdom switch on different Sundays.
- Sydney is in the southern hemisphere, so it is
UTC+11in January andUTC+10in July, the opposite season of Europe.
Offsets are not always whole hours either: India is UTC+5:30, Nepal is UTC+5:45 and the Chatham Islands in New Zealand are UTC+12:45 in winter and UTC+13:45 in summer.
That is why a converter must use the rules of the date you pick, not of today. The Time Zone Converter on this site does exactly that: noon in São Paulo on 1 July 2026 is 11:00 in New York, 16:00 in London and already 00:00 on 2 July in Tokyo.
Times that do not exist, and times that happen twice
Daylight saving creates two strange situations once a year in each zone that uses it.
The skipped hour. On 8 March 2026, clocks in New York jump from 01:59 straight to 03:00. A time like 02:30 that day never happens. Libraries handle it differently: some throw an error, some move it forward. The converter on this site moves it to the first valid time, 03:30.
The repeated hour. On 1 November 2026, clocks in New York go back from 01:59 to 01:00. The interval from 01:00 to 01:59 happens twice, first at UTC−4 and then at UTC−5. A local time like 01:30 that day is ambiguous; you need the offset to know which one is meant.
If your application schedules jobs at local times, avoid the window between 01:00 and 03:00 when you can, and test those two dates explicitly.
Rules for code
Most time zone bugs disappear with a few habits:
- Store instants in UTC. In a database, use a type that represents an instant, such as
timestamptzin PostgreSQL, or a Unix timestamp. Never store local time without its zone. - Store the zone separately when it matters. A recurring meeting "every Monday at 10:00 in São Paulo" needs
America/Sao_Paulo, not a fixed offset, so that future dates follow future rules. - Convert at the edges. Read and write UTC everywhere in the system, and convert to local time only when showing a date to a person, using their zone.
- Use the platform's time zone database. In JavaScript,
Intl.DateTimeFormatwith thetimeZoneoption. In Python, thezoneinfomodule. In Java,java.time.ZonedDateTime. Do not hard-code offsets. - Send ISO 8601 with an offset or a
Z.2026-07-01T15:00:00Zand2026-07-01T12:00:00-03:00are the same instant and are unambiguous.2026-07-01 12:00is not.
A minimal example in JavaScript, showing one instant in several zones:
const instant = new Date("2026-07-01T15:00:00Z");
for (const timeZone of ["America/Sao_Paulo", "America/New_York", "Asia/Tokyo"]) {
const time = new Intl.DateTimeFormat("en-GB", {
timeZone,
dateStyle: "medium",
timeStyle: "short",
}).format(instant);
console.log(timeZone, time);
}
// America/Sao_Paulo 1 Jul 2026, 12:00
// America/New_York 1 Jul 2026, 11:00
// Asia/Tokyo 2 Jul 2026, 00:00And the same idea in Python:
from datetime import datetime
from zoneinfo import ZoneInfo
meeting = datetime(2026, 7, 1, 12, 0, tzinfo=ZoneInfo("America/Sao_Paulo"))
print(meeting.astimezone(ZoneInfo("Europe/London")))
# 2026-07-01 16:00:00+01:00Common mistakes
- Treating an offset as a zone.
-05:00is right for New York only part of the year. - Using abbreviations as identifiers.
CSTandISTmean different things in different countries. - Computing with today's rules. A meeting in July needs July's offsets.
- Adding 24 hours to get "tomorrow at the same time". On the day DST changes, a day has 23 or 25 hours. Add one calendar day in the zone instead.
- Trusting the server's local time. Servers should run in UTC; never let the machine's zone leak into stored data.
- Forgetting that the database changes. Keep your runtime and tzdata updated, since rules change every year somewhere.
Summary
UTC is the reference, an offset is a distance from UTC at a moment, and a time zone is a set of rules that decides which offset applies on each date. Because daylight saving starts and ends on different dates around the world, the gap between two cities changes during the year, and some local times are skipped or repeated. Store instants in UTC, keep IANA zone names when the local time matters, and convert with the rules of the actual date.
Keep reading
Base64 is not encryption — what it is, when to use it and the URL-safe variant
How Base64 turns bytes into text, why it hides nothing, how to handle accents and emoji correctly and when you need the URL-safe alphabet.
November 5, 20265 min readTool: Base64 Encoder/Decoder
The regex that freezes the browser — catastrophic backtracking explained
Why a short regular expression can take seconds or hang a page, how to recognize nested quantifiers and how to rewrite the pattern so it stays fast.
November 5, 20266 min readTool: Regex Tester