← 모든 글

밀리초 vs 초: millis를 Unix 타임스탬프로 변환하는 법

가장 흔한 타임스탬프 버그는 초가 기대되는 곳에 밀리초를 넘기거나 그 반대입니다. 10자리 대 13자리 규칙, 언어별 기본값, 데이터베이스 영향, 안전한 변환 패턴을 배웁니다.

왜 두 가지 표준이 있나

Unix 시간은 원래 초로 정의되었습니다. 클록 틱마다 1씩 증가하는 시스템에는 정수가 자연스러웠습니다. JavaScript의 Date 객체는 1995년에 도입되어, 브라우저에서 1초 미만 이벤트 타이밍을 지원하기 위해 밀리초를 선택했습니다. 많은 데이터베이스와 백엔드 언어는 Unix 초를 기본값으로 유지했습니다. 이제 두 표준은 JavaScript와 서버 경계를 넘는 모든 코드에 공존하며, 그래서 어떤 값이 유효해 보이면서도 수만 년 뒤의 날짜를 나타낼 수 있습니다.

언어마다 쓰는 단위

구분을 기억하는 가장 안전한 방법: 브라우저 Date API는 보통 밀리초를 원하고, Unix 스타일 서버 API는 보통 초를 노출하며, 최신 시간 라이브러리는 둘 다 제공하는 경우가 많습니다. 서드파티 API 문서를 읽을 때 언어만으로 단위를 추론하지 말고 필드 설명과 예제를 확인하세요.

  • 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)

값으로 단위 자동 감지

현대 날짜에 대한 신뢰할 수 있는 휴리스틱: 10자리 숫자는 초, 13자리는 밀리초입니다. 현재 Unix 초는 약 17~21억(10자리)이며 서기 33658년까지 13자리가 되지 않습니다. 현재 Unix 밀리초는 이미 13자리입니다. 이 휴리스틱은 2000년대부터 수천 년 뒤까지 가장 강력합니다. 역사적·음수 날짜나 짧은 테스트 픽스처에서는 추측 대신 명시적 단위를 사용하세요.

  • 10자리 값 → 초(예: 1700000000 = 2023-11-14 UTC)
  • 13자리 값 → 밀리초(예: 1700000000000 = 2023-11-14 UTC)
  • 16자리 값 → 마이크로초(초로 만들려면 1,000,000으로 나눔)
  • 음수 값 → 1970년 1월 1일 이전 날짜(초 또는 밀리초)

안전한 변환 패턴

변환 자체는 단순한 산술입니다. 어려운 부분은 변환을 어디서 할지 정하는 것입니다. 시스템 경계에서 변환하고, 변환된 값에 이름을 붙이며, 모호한 원시 숫자를 여러 계층에 그대로 넘기지 마세요.

  • 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

단위 버그가 프로덕션에서 나타나는 방식

초 대 밀리초 버그는 두 값 모두 그냥 숫자이기 때문에 검증을 통과하기 쉽습니다. 보통 나중에 불가능한 날짜로 나타납니다: 초를 밀리초로 다루면 JavaScript에서 1970년 1월, 백엔드가 밀리초를 초로 다루면 먼 미래 연도가 됩니다.

  • JavaScript UI에서 1970년 날짜 → 1000을 곱하지 않고 초를 new Date()에 넘김
  • Python·Go·PHP에서 50000년 이상 → 초를 기대하는 API에 밀리초를 넘김
  • 만료되지 않는 만료 토큰 → 만료 타임스탬프를 잘못된 단위로 저장
  • 즉시 사라지는 캐시 항목 → 밀리초를 두 번 나누거나 초를 두 번 곱함
  • 범위가 빈 분석 차트 → 쿼리 경계가 저장된 이벤트 타임스탬프와 다른 단위를 사용

API와 데이터베이스 명명 규칙

작은 명명 규칙이 이런 버그의 대부분을 막습니다. 문서가 매우 명확하지 않은 한 timestamp라는 API 필드를 절대 공개하지 마세요. 의미와 단위를 모두 담은 필드 이름을 선호하세요.

  • 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

밀리초 vs 초 FAQ

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.