JavaScript Date.now(): obtener y convertir timestamps Unix
Una guía centrada en JavaScript Date.now(): obtén el timestamp Unix actual, convierte segundos frente a milisegundos, transforma timestamps en objetos Date, formatea con Intl y evita las trampas de parseo más comunes.
Cómo almacena JavaScript el tiempo internamente
Cada Date de JavaScript es internamente un único float de 64 bits que representa milisegundos desde el epoch Unix (1 de enero de 1970 00:00:00 UTC). Ese número es lo que devuelven Date.getTime() y Date.now(). No hay ninguna zona horaria guardada dentro de un Date: siempre es un recuento de milisegundos UTC. La información de zona horaria solo importa al formatear la fecha para mostrarla, y por eso el mismo objeto Date puede aparecer como lunes por la noche en Los Ángeles y martes por la mañana en Tokio. Este artículo se centra en Date.now() y en convertir timestamps; para un recorrido más amplio de cada tarea de timestamp en JavaScript, consulta la guía de referencia completa enlazada abajo.
Obtener el timestamp Unix actual
Usa Date.now() para milisegundos y Math.floor(Date.now() / 1000) para segundos. Ambos tienen amplio soporte y no requieren imports. El hábito de nombrado importante es incluir la unidad en el nombre de la variable: createdAtMs, expiresAtSeconds o unixSeconds. Los nombres con unidad evitan que un futuro consumidor de la API adivine qué significa un campo de timestamp sin unidad.
- Date.now() → 1700000000000 (milliseconds, 13 digits)
- Math.floor(Date.now() / 1000) → 1700000000 (seconds, 10 digits)
- +new Date() → same as Date.now() via unary coercion
- new Date().getTime() → same result, slightly more verbose
Date.now() vs performance.now()
Date.now() es para timestamps de reloj: logs, payloads de API, campos de base de datos, expiración de caché y cualquier cosa que deba alinearse con el tiempo de calendario real. performance.now() es para medir la duración transcurrida dentro de la página o el proceso actual. Es monótono y de alta precisión, pero no es un timestamp Unix y no puede convertirse en una fecha real sin un punto de referencia adicional.
- Usa Date.now() cuando el valor se vaya a almacenar, enviar a una API o mostrar como fecha
- Usa performance.now() al medir cuánto tardó el renderizado, el parseo o una petición
- No guardes performance.now() en una base de datos como tiempo de evento
- No restes dos valores de Date.now() para temporización sensible a la seguridad; los cambios del reloj del sistema pueden afectarlos
Convertir un timestamp en un Date
El constructor Date acepta milisegundos. Si tu timestamp está en segundos (10 dígitos), multiplica por 1000 antes de pasarlo. Olvidar esto es el error de timestamp más común en JavaScript. Una comprobación rápida es el número de dígitos: los segundos Unix actuales tienen 10 dígitos, los milisegundos Unix actuales tienen 13 dígitos, y una llamada al constructor Date debería recibir la forma de 13 dígitos en milisegundos.
- new Date(1700000000 * 1000) → Tue Nov 14 2023 22:13:20 UTC ✓ correct
- new Date(1700000000) → Tue Jan 20 1970 16:13:20 UTC ✗ missing × 1000
- new Date(1700000000 * 1000).toISOString() → '2023-11-14T22:13:20.000Z'
- new Date(1700000000 * 1000).toUTCString() → 'Tue, 14 Nov 2023 22:13:20 GMT'
Formato con zona horaria usando Intl
Usa Intl.DateTimeFormat para una salida según la configuración regional y la zona horaria. Gestiona el horario de verano automáticamente y no requiere librerías externas. Es la vía integrada más segura para paneles, herramientas de administración, páginas de estado y timestamps de cara al usuario, porque te permite elegir tanto la configuración regional como la zona horaria IANA de forma explícita.
- new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'long' }).format(date)
- date.toLocaleString('en-GB', { timeZone: 'Europe/London', hour12: false })
- date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
- new Intl.DateTimeFormat('en-CA', { timeZone: tz }).formatToParts(date) → array of {type, value} for custom layouts
Parsear cadenas de fecha de forma segura
El parseo es donde JavaScript se vuelve sorprendente. Las cadenas ISO con una Z u offset explícitos son seguras porque identifican un instante exacto. Las fechas escuetas y las cadenas informales son más fáciles de leer, pero a menudo dependen de las reglas del navegador o de la zona horaria del entorno. Para los contratos de API, prefiere cadenas ISO 8601 con zona horaria o timestamps Unix numéricos con la unidad escrita en el nombre del campo.
- Safe: new Date('2026-05-19T14:30:00Z') — explicit UTC
- Safe: new Date('2026-05-19T10:30:00-04:00') — explicit offset
- Risky: new Date('05/19/2026') — locale-dependent and ambiguous
- Risky: new Date('2026-05-19 10:30') — not a strict ISO timestamp in all runtimes
Errores comunes de timestamp en JavaScript
- new Date(1700000000) en vez de new Date(1700000000 * 1000) — cae en 1970, no en 2023
- getMonth() devuelve 0–11, no 1–12 — usa siempre date.getMonth() + 1 al mostrar
- new Date('2024-01-01') se parsea como medianoche UTC; new Date('2024/01/01') como medianoche local
- Sumar 86400000 ms para «mañana» se rompe en las transiciones de horario de verano — usa setDate(d.getDate() + 1)
- Comparar objetos Date con === siempre falla — compara sus valores .getTime()
Lista recomendada de timestamps en JavaScript
El patrón de producción más simple es almacenar un único instante canónico y formatearlo solo en el borde. Mantén los timestamps en UTC, incluye las unidades en los nombres y convierte a una zona horaria legible solo en la interfaz o la capa de informes.
- Usa milisegundos Unix para el estado solo de navegador y la construcción de Date en JavaScript
- Usa segundos Unix al llamar a APIs que documentan el tiempo Unix en segundos
- Usa ISO 8601 con Z o un offset explícito cuando personas puedan inspeccionar los payloads
- Usa Intl.DateTimeFormat con una timeZone explícita para mostrar
- Añade tests alrededor de los límites del horario de verano cuando importen las fechas de calendario locales
Preguntas frecuentes sobre timestamps en JavaScript
- ¿Date.now() devuelve segundos o milisegundos?
- Date.now() devuelve milisegundos desde el 1 de enero de 1970 00:00:00 UTC. Divide entre 1000 y usa Math.floor() cuando una API espera segundos Unix.
- ¿Por qué new Date(1700000000) muestra 1970?
- El constructor Date espera milisegundos. 1700000000 es un timestamp en segundos, así que JavaScript lo lee como solo 1.700 millones de milisegundos tras el epoch. Usa new Date(1700000000 * 1000).
- ¿Un Date de JavaScript guarda una zona horaria?
- No. Un Date guarda un recuento de milisegundos UTC. La zona horaria se aplica solo al formatear con métodos como toString(), toLocaleString() o Intl.DateTimeFormat.
- ¿Cómo convierto un timestamp Unix en un Date de JavaScript?
- Pasa milisegundos al constructor: new Date(seconds * 1000) para un valor de 10 dígitos en segundos, o new Date(ms) para un valor de 13 dígitos en milisegundos. Olvidar el × 1000 es por lo que un timestamp de 2023 puede mostrarse como 1970.