¿Odias los anuncios? Ir Sin publicidad Hoy

Los horarios de zona son una mentira (y cómo manejarlos en el código)

Publicado el

Time zones look simple on a map. They're not. Here's why they break software — and the right mental model for handling them in code.

Las zonas horarias son una mentira (y cómo manejarlas en el código) 1
ANUNCIO · ¿ELIMINAR?

You open a map. You see vertical slices. “UTC-5 is Eastern Time, UTC+1 is Central European Time.” Simple, right?

Wrong. Time zones are a political construction, not a geographic fact — and that distinction will save you from some of the nastiest bugs in software development.

Why Time Zones Are Actually a Mess

Here’s what your operating system’s tz database quietly handles on your behalf:

  • Daylight Saving Time (DST) — Not every country observes it, countries change the rules, and the switch happens on different dates depending on where you are. The US switched dates in 2007. Egypt abolished DST in 2011, then reinstated it, then abolished it again.
  • Half-hour and quarter-hour offsets — India (UTC+5:30), Nepal (UTC+5:45), and parts of Australia (UTC+9:30) exist. Your assumption that offsets are whole hours is wrong.
  • Historical changes — Russia moved from UTC+4 to UTC+3 in 2014. Samoa skipped an entire day (December 30, 2011) to move from one side of the International Date Line to the other. When you’re dealing with historical timestamps, the “correct” offset can be completely different from today’s.
  • Ambiguous times — When clocks fall back, 1:30 AM happens twice. When they spring forward, 2:30 AM doesn’t exist at all. If you store “November 3, 2024 at 1:45 AM Eastern” without a UTC offset, you have an ambiguous timestamp.

None of this is trivia. Every one of these edge cases has caused real production bugs — missed calendar events, double-charged payments, broken scheduling systems.

The One Rule That Fixes Most Problems

Store and process in UTC. Convert to local time only at display time.

This is not controversial advice. It’s the consensus of every major database, API standard, and distributed systems team. If your database column stores 2024-11-03 06:45:00 in UTC, you always know exactly what moment in time that represents — regardless of where your server is hosted, what time zone your user is in, or whether DST happened that day.

The moment you store 2024-11-03 01:45:00 without a UTC offset, you’ve lost information. You’ve created a timestamp that means two different things.

How to Handle Time Zones in JavaScript

JavaScript’s built-in Date object stores time as milliseconds since the Unix epoch (January 1, 1970 UTC) — which is good. The problem is that its API is confusing and inconsistent.

What to avoid

// BAD: Parsing without explicit timezone
const d = new Date('2024-11-03 01:45:00');
// Interpreted as LOCAL time — behavior varies by environment

// BAD: Storing user-facing strings as dates
const meeting = '3:00 PM Thursday';
// This is meaningless without a timezone

What to use instead

// GOOD: Always use ISO 8601 with explicit UTC offset
const d = new Date('2024-11-03T06:45:00Z'); // Z = UTC

// GOOD: Display in user's local timezone using Intl API
const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/New_York',
  dateStyle: 'full',
  timeStyle: 'short',
});
console.log(formatter.format(d)); // "Sunday, November 3, 2024 at 1:45 AM"

If you’re building anything beyond simple date formatting, use the Luxon library. It has first-class timezone support, handles DST transitions correctly, and makes the intent of your code obvious.

import { DateTime } from 'luxon';

// Parse an ISO string and convert to a specific zone
const utc = DateTime.fromISO('2024-11-03T06:45:00Z');
const eastern = utc.setZone('America/New_York');
console.log(eastern.toLocaleString(DateTime.DATETIME_FULL));
// "November 3, 2024, 1:45 AM EDT"

How to Handle Time Zones in Python

Python’s datetime module distinguishes between naive (no timezone) and aware (with timezone) datetime objects. Naive datetimes are a footgun — avoid them in any code that crosses time zone boundaries.

from datetime import datetime, timezone
import zoneinfo  # Python 3.9+

# BAD: naive datetime (no timezone info)
d = datetime(2024, 11, 3, 1, 45, 0)

# GOOD: always attach a timezone
d_utc = datetime(2024, 11, 3, 6, 45, 0, tzinfo=timezone.utc)

# Convert to a specific timezone
eastern = zoneinfo.ZoneInfo('America/New_York')
d_eastern = d_utc.astimezone(eastern)
print(d_eastern)  # 2024-11-03 01:45:00-05:00

For older Python or more complex scheduling needs, python-dateutil y Flecha are both well-maintained choices. The key principle stays the same: work in UTC, convert at the boundary.

How to Handle Time Zones in Databases

Database timezone handling trips up even experienced developers.

PostgreSQL

PostgreSQL has two timestamp types: timestamp (no timezone) and timestamptz (with timezone). Despite the name, timestamptz doesn’t actually store the timezone — it converts to UTC on write and converts back to the session timezone on read. That’s the correct behavior. Always use timestamptz.

-- BAD
CREATE TABLE events (created_at TIMESTAMP);

-- GOOD
CREATE TABLE events (created_at TIMESTAMPTZ);

-- Querying across timezones
SELECT created_at AT TIME ZONE 'America/New_York' FROM events;

MySQL

MySQL’s DATETIME stores with no timezone context — what you put in is what you get out, no conversion. TIMESTAMP converts to UTC on write and back to the current server timezone on read — but it’s limited to dates between 1970 and 2038 (the Unix timestamp overflow). In practice: use DATETIME columns and ensure your application always writes UTC values explicitly.

Scheduling Across Time Zones: The Hidden Trap

Suppose a user schedules a recurring weekly meeting for “every Monday at 9 AM New York time.” You store the next occurrence as a UTC timestamp. Fine — until DST changes, and now the UTC time you stored corresponds to 10 AM New York time instead of 9 AM.

The fix: don’t store absolute future timestamps for recurring events. Store the local rule — the time zone identifier + the local time — and compute the next UTC timestamp at runtime. This way, the system recalculates correctly after DST transitions.

-- Store the intent, not the absolute moment
CREATE TABLE recurring_events (
  id SERIAL PRIMARY KEY,
  timezone TEXT NOT NULL,       -- 'America/New_York'
  local_time TIME NOT NULL,     -- '09:00:00'
  recurrence TEXT NOT NULL      -- 'WEEKLY:MONDAY'
);
-- Compute next_occurrence_utc in application code at dispatch time

IANA Time Zone Names vs UTC Offsets

When storing a user’s time zone preference, store the IANA name (America/New_York, Europe/London, Asia/Kolkata) — not the UTC offset (UTC-5, UTC+1). Offsets are snapshots; IANA names encode the full DST history and future rules.

America/New_York es UTC-5 in winter and UTC-4 in summer. If you store UTC-5, you’re baking in the wrong offset half the year.

Quick Reference: The Rules

  • Store timestamps as UTC — always, no exceptions in your database or API responses.
  • Use IANA timezone names — not UTC offsets — for user preferences and recurring schedules.
  • Never parse date strings without an explicit timezone — the implicit behavior is environment-dependent.
  • Convert to local time at the display layer — not in your business logic or database queries.
  • For recurring schedules, store the rule — not the precomputed UTC time — so DST transitions don’t corrupt future occurrences.
  • Test with edge cases — the DST transition hour, dates near the International Date Line, and historical timestamps in regions that have changed their offset.
¿Quieres eliminar publicidad? Adiós publicidad hoy

Instalar extensiones

Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas

añadir Extensión de Chrome añadir Extensión de borde añadir Extensión de Firefox añadir Extensión de Opera

¡El marcador ha llegado!

Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!

ANUNCIO · ¿ELIMINAR?
ANUNCIO · ¿ELIMINAR?
ANUNCIO · ¿ELIMINAR?

Noticias Aspectos técnicos clave

Involucrarse

Ayúdanos a seguir brindando valiosas herramientas gratuitas

Invítame a un café
ANUNCIO · ¿ELIMINAR?