Por qué hay dos estándares
El tiempo Unix se definió originalmente en segundos: un entero parecía natural para un sistema que se incrementaba en cada tic de reloj. El objeto Date de JavaScript se introdujo en 1995 y eligió milisegundos para soportar la temporización de eventos por debajo del segundo en el navegador. Muchas bases de datos y lenguajes de backend mantuvieron los segundos Unix como valor por defecto. Hoy ambos estándares coexisten en todo código que cruza la frontera JavaScript-servidor, y por eso un valor puede parecer válido y aun así representar una fecha a decenas de miles de años.
Qué unidad usa cada lenguaje
La forma más segura de recordar la división es: las APIs Date del navegador suelen querer milisegundos, las APIs de servidor al estilo Unix suelen exponer segundos, y las librerías de tiempo más nuevas a menudo ofrecen ambos. No deduzcas la unidad solo por el lenguaje al leer la documentación de una API de terceros; comprueba la descripción del campo y los ejemplos.
- Milliseconds: JavaScript Date.now(), Java System.currentTimeMillis(), Java Instant.toEpochMilli(), .NET ToUnixTimeMilliseconds()
- Seconds: Python time.time() (float), PHP time(), Go time.Now().Unix(), Ruby Time.now.to_i, C time(NULL), PostgreSQL EXTRACT(EPOCH)
- Both: Rust — duration.as_secs() for seconds, duration.as_millis() for milliseconds
- Python note: time.time() returns a float, so milliseconds are available as int(time.time() * 1000)
Detectar la unidad a partir del valor
Una heurística fiable para fechas modernas: un número de 10 dígitos son segundos; uno de 13 dígitos son milisegundos. Los segundos Unix actuales rondan los 1700–2100 millones (10 dígitos) y no llegarán a 13 dígitos hasta el año 33658. Los milisegundos Unix actuales ya tienen 13 dígitos. La heurística es más fuerte para fechas desde los 2000 hasta dentro de varios miles de años; para fechas históricas, negativas o fixtures de prueba compactos, usa unidades explícitas en vez de adivinar.
- valor de 10 dígitos → segundos (p. ej. 1700000000 = 2023-11-14 UTC)
- valor de 13 dígitos → milisegundos (p. ej. 1700000000000 = 2023-11-14 UTC)
- valor de 16 dígitos → microsegundos (divide entre 1,000,000 para segundos)
- valor negativo → fecha anterior al 1 de enero de 1970 (segundos o milisegundos)
Patrones de conversión seguros
La conversión en sí es aritmética simple; lo difícil es elegir dónde debe ocurrir. Convierte en el límite del sistema, nombra el valor convertido y evita pasar números crudos ambiguos por varias capas.
- Seconds to milliseconds: seconds * 1000
- Milliseconds to whole seconds — JavaScript: Math.floor(ms / 1000)
- Milliseconds to whole seconds — Python: ms // 1000
- Milliseconds to whole seconds — Go: ms / 1000 (integer division)
- Universal guard in JavaScript: const toMs = ts => ts < 1e11 ? ts * 1000 : ts
Cómo aparecen los bugs de unidad en producción
Un bug de segundos-vs-milisegundos suele sobrevivir a la validación porque ambos valores son solo números. Suele aparecer más tarde como una fecha imposible: enero de 1970 en JavaScript cuando se trataron segundos como milisegundos, o un año muy lejano cuando un backend trató milisegundos como segundos.
- Fecha de 1970 en la UI de JavaScript → se pasaron segundos a new Date() sin multiplicar por 1000
- Año 50000+ en Python, Go o PHP → se pasaron milisegundos a una API que esperaba segundos
- Tokens caducados que nunca expiran → el timestamp de caducidad se guardó en la unidad equivocada
- Entradas de caché que desaparecen al instante → milisegundos divididos dos veces o segundos multiplicados dos veces
- Gráficos de analítica con rangos vacíos → los límites de la consulta usan una unidad distinta a la de los timestamps de eventos guardados
Convenciones de nombres en APIs y bases de datos
Una pequeña convención de nombres evita la mayoría de estos bugs. No publiques nunca un campo de API llamado timestamp salvo que la documentación sea excepcionalmente clara. Prefiere nombres de campo que incluyan el significado y la unidad.
- createdAtMs — Unix milliseconds, best for JavaScript clients
- createdAtSeconds — Unix seconds, common for backend services
- createdAtIso — ISO 8601 string, useful for human-readable API responses
- expiresAtUnixSeconds — explicit enough for auth tokens and signed URLs
- event_time TIMESTAMPTZ — native database time, with conversion handled by the database
Preguntas frecuentes sobre milisegundos vs segundos
A tiny naming convention prevents most of these bugs. Never publish an API field called timestamp unless the documentation is unusually clear. Prefer field names that include both meaning and unit.
- createdAtMs — Unix milliseconds, best for JavaScript clients
- createdAtSeconds — Unix seconds, common for backend services
- createdAtIso — ISO 8601 string, useful for human-readable API responses
- expiresAtUnixSeconds — explicit enough for auth tokens and signed URLs
- event_time TIMESTAMPTZ — native database time, with conversion handled by the database
Microseconds (16 digits) and nanoseconds (19 digits)
Most production timestamps are seconds (10 digits) or milliseconds (13 digits), but two higher-precision formats also appear in real systems — microseconds and nanoseconds. The same digit-counting rule extends.
- 10 digits ≈ Unix seconds (~1.7×10⁹ today)
- 13 digits ≈ Unix milliseconds (~1.7×10¹²)
- 16 digits ≈ Unix microseconds (~1.7×10¹⁵) — Python time.time_ns()/1000, Postgres TIMESTAMP precision 6
- 19 digits ≈ Unix nanoseconds (~1.7×10¹⁸) — Java Instant.toEpochNano(), Go time.UnixNano(), Temporal.Instant.epochNanoseconds
- PostgreSQL to_timestamp() takes seconds with an optional fractional part; passing milliseconds yields a date around the year 55000
- Convert from any precision to milliseconds via integer arithmetic before doing further math
- Silent truncation: if a database column has millisecond precision but you store nanoseconds, the bottom 6 digits are dropped on insert
How many microseconds in a second? 1 second to milliseconds, microseconds to milliseconds
A quick reference for the unit math that drives every seconds/milliseconds/microseconds bug. The questions "how many microseconds in a second", "1 second to milliseconds", and "microseconds to milliseconds" are all powers of 1000 — but every order of magnitude is one place where production code goes wrong. Keep the table below within reach when writing high-resolution timestamp code.
- 1 second to milliseconds = 1,000 ms (10³)
- How many microseconds in a second? = 1,000,000 µs (10⁶)
- 1 second to nanoseconds = 1,000,000,000 ns (10⁹)
- Microseconds to milliseconds = µs ÷ 1,000 (10³ step down)
- Milliseconds to microseconds = ms × 1,000
- Nanoseconds to microseconds = ns ÷ 1,000
- Common precision: JavaScript Date.now() = ms, performance.now() = sub-ms float, Go time.UnixNano() = ns, Postgres TIMESTAMP precision 6 = µs
- Bug pattern: an API returns µs, code divides by 1000 once expecting seconds — actually got ms; result is 1000× off
Millisecond timer, time to ms, milliseconds to seconds conversion
Quick reference for the unit phrasings: "time to ms" (any time value scaled into milliseconds), "milliseconds to seconds conversion" (÷1000), and "millisecond timer" (a high-resolution timer for short intervals). For measuring elapsed time prefer a monotonic clock — wall-clock time can jump backwards on NTP correction or DST.
- Time to ms / time to milliseconds: seconds × 1000 = ms; microseconds ÷ 1000 = ms; nanoseconds ÷ 1,000,000 = ms
- Milliseconds to seconds conversion: ms ÷ 1000 = seconds; Math.floor(ms/1000) for integer seconds
- Millisecond timer (JavaScript): performance.now() returns sub-ms float since page load; Date.now() returns wall-clock ms
- Millisecond timer (Python): time.perf_counter() (monotonic float seconds); time.monotonic_ns() returns ns
- Millisecond timer (Java): System.nanoTime() for monotonic ns; Instant.now() for wall-clock ns precision
- Stopwatch rule: use monotonic clocks for elapsed time; wall-clock can jump backwards on NTP or DST
FAQ
- Is a 13-digit timestamp always milliseconds?
- For modern real-world Unix timestamps, yes: 13 digits usually means milliseconds. Very far-future seconds timestamps can also reach 13 digits, so critical systems should still carry explicit unit metadata.
- Should I store seconds or milliseconds?
- Store the unit your system naturally uses, but document it and keep it consistent. JavaScript-heavy systems often use milliseconds; Unix-style backends and many databases commonly use seconds or native datetime columns.
- Why use Math.floor(ms / 1000) instead of ms / 1000?
- Unix seconds are usually whole seconds. Math.floor removes the fractional part so APIs expecting integer seconds do not receive a decimal value.
- How do I convert milliseconds to seconds?
- Divide by 1000 and drop the fraction: Math.floor(ms / 1000) in JavaScript, ms // 1000 in Python, or ms / 1000 with integer division in Go. To go the other way, multiply seconds by 1000.