2P by GN⁺ | ★ favorite | 댓글 1개
  • POSIX time/Unix time은 흔히 1970-01-01 00:00:00 이후의 초 수로 불리지만, 실제로는 윤초를 무시한 UTC 기반 값이라 실제 경과 초와 어긋남
  • 2024-12-25 18:51:26 UTC 기준 POSIX time은 1735152686이고, epoch 이후 실제 경과 초는 1735152713초라 27초 차이가 남
  • IEEE 1003.1은 seconds since the Epoch를 정의할 때 하루를 항상 86,400초로 계산하며, 표준 부록도 1970년 이후 추가된 윤초 14초를 호환성과 계산 편의를 위해 무시함
  • UTC는 태양일과의 차이를 줄이기 위해 윤초를 추가하고, 이때 POSIX time이 뒤로 점프하면서 Linux, Qantas, Cloudflare DNS 같은 장애 사례가 생김
  • 단일 컴퓨터의 시간 간격 측정에는 CLOCK_MONOTONIC 또는 CLOCK_BOOTTIME이 낫고, POSIX timestamp와 맞춰야 한다면 leap smear나 POSIX↔TAI 변환을 고려해야 함

POSIX time은 실제 경과 초 수가 아님

  • JavaScript Date, GNU coreutils, Linux time(2), Go time.Unix, MySQL datetime, Ruby Time, Cassandra timestamp 등은 POSIX time을 흔히 Unix epoch 이후 초 수처럼 다룸
  • 하지만 이 표현은 일반적인 직관과 정확히 맞지 않음
    • 예시 시각: 2024-12-25 18:51:26 UTC
    • POSIX time: 1735152686
    • POSIX epoch 이후 실제 경과 초: 1735152713
    • 차이: 27초
  • 이 차이는 POSIX time이 IEEE 1003.1에서 UTC로부터 파생되면서도, 모든 날을 정확히 86,400초로 가정하기 때문에 생김
  • 표준의 seconds since the Epoch 정의는 tm_sec, tm_min, tm_hour, tm_yday, tm_year를 이용해 값을 계산하며, 연도 1970 미만이거나 음수인 값과의 관계는 정의하지 않음
  • 실제 하루의 길이는 항상 86,400초가 아니고 시간에 따라 달라짐
    • UTC 날짜가 태양일에서 너무 멀어지지 않도록 천문학자들이 주기적으로 윤초를 선언함
    • 그 결과 POSIX time은 몇 년마다 뒤로 점프할 수 있음
    • 언젠가는 앞으로 점프할 수도 있음
  • 윤초는 실제 장애로 이어진 적이 있음

표준의 타협과 실무 대안

  • IEEE 1003 부록 B는 표준 발행 시점에 1970-01-01 이후 14개 윤초가 추가됐지만, 쉬운 계산과 호환성을 위해 이 14초를 무시한다고 정리함
  • 표준은 대부분 시스템의 “time” 값이 계속 증가한다고 보고, 윤초 중에도 이 값이 증가해야 한다는 쪽을 택함
    • 동시에 대부분 시스템이 윤초를 추적하지 않거나 표준 시간 기준에 동기화되지 않을 수 있음을 전제함
    • 그래서 seconds since the Epoch가 참조 시각과 epoch 사이의 정확한 초 수를 반드시 나타내야 한다고 요구하지 않음
    • 애플리케이션이 이 값을 epoch 이후 초 수처럼 취급할 수 있으면 충분하며, 필요한 정확도는 시스템 공급업체와 관리자가 맞춰야 한다는 입장임
  • 분산 애플리케이션에서는 timestamp로 이벤트를 동기화하므로 일관된 해석이 중요해질 수 있음
    • 윤초 누적은 예측할 수 없음
    • epoch 이후 윤초 수는 늘어날 가능성이 있음
    • 표준은 천문학적으로 짧은 기간의 애플리케이션 간 시간 동기화에 더 관심을 둠
  • 실제 시스템은 시간이 약간 어긋나도 대체로 동작하지만, 윤초는 드물고 “epoch 이후 초 수”라는 선형적 직관이 강해 발견되지 않은 버그가 쌓일 수 있음
  • 상황별 대안은 다음과 같음
    • 한 컴퓨터에서 두 이벤트 사이의 duration만 계산하면 CLOCK_MONOTONIC, 더 나아가 CLOCK_BOOTTIME 사용
    • POSIX time을 가정하는 다른 시스템과 timestamp를 교환할 필요가 없다면 TAI, GPS, LORAN 사용
    • POSIX timestamp 시스템들과 대략 맞춰야 하면 leap smear로 윤초를 더 긴 시간 구간에 분산
    • qntm의 t-a-i 같은 라이브러리로 POSIX와 TAI 간 변환 가능
  • 윤초를 폐지하려는 노력이 진행 중이며, 2035년까지 실현되기를 기대하고 있음
    • 하루 86,400초 가정에 의존하는 모든 것에 변환 테이블을 넣는 추가 작업이 필요함
    • 2035년 이후 시각에 대해서는 “두 시각 사이에 몇 초가 있는가” 같은 질문이 훨씬 단순해질 수 있음

댓글과 토론

Hacker News 의견들
  • Vernor Vinge의 2000년 SF 소설 A Deepness in the Sky를 막 읽었는데, epoch 이후 초(seconds since the epoch)에 대한 뜻밖의 언급이 나오는 훌륭한 책임
    “Traders의 시간 측정 방식을 보라…”로 시작해, Qeng Ho가 인류가 Old Earth의 달에 처음 발을 디딘 순간부터 초 단위로 세지만, 더 자세히 보면 시작 시점이 실제로는 약 1,500만 초 뒤, 인류 초기 컴퓨터 운영체제 중 하나의 0초였다는 식으로 묘사됨

    • 이 책은 개인적으로 역대 최애 중 하나이고, 은근한 소프트웨어 레퍼런스를 쓰는 방식이 정말 좋음
      “우주 속 컴퓨터 과학”을 더 원한다면 Bobiverse 시리즈를, “인간 + 시뮬레이션 + 컴퓨터” 탐구를 더 원한다면 Permutation City를 추천함
  • 시간 측정에 대해 읽을 때마다 빠짐없이 새로 배우게 됨. Unix 시간은 롤오버만 고려하면 시간을 추적하는 가장 단순한 방식이라고 생각해 왔고, 윤초는 알고 있었지만 여기에도 적용된다는 생각은 못 했음
    “UTC, GPS, LORAN and TAI” 링크도 읽었는데, GPS 시간이 윤초를 반영하지 않는다는 점이 흥미로운 대비임

    • 어떤 일이 몇 초 전/후에 일어났다고 말하는 건 단순함. 어려운 건 그 시점을 달력 날짜로 부여하는 쪽임
    • 결론적으로 TAI가 가장 단순하고, 다른 형식은 필요할 때만 TAI에서 변환해 써야 한다고 보게 됨. 예를 들면 표시나 상호운용성을 위해서임
  • “2035년까지 윤초를 없애려는 노력이 진행 중”이라는 계획은 별로 마음에 들지 않음
    UTC의 핵심은 TAI에서 정수 초만큼 떨어져 평균태양시(MST)에 근접하는 것임. 더 이상 MST를 추적하지 않겠다면 그냥 TAI로 전환해야 함
    UTC가 MST에서 멀어지게 두면, 과거 윤초는 계속 처리해야 하지만 그 윤초가 더 이상 목적을 갖지 않는 어정쩡한 상태가 됨

    • MST에서 벗어나는 건 얻는 것보다 비용이 더 크다는 데 동의함
      다만 이 제안이 완전히 무의미한 건 아님. 기존 UTC 시간 관리는 바꾸지 않고, 2035년 이후의 두 타임스탬프 차이가 정확한 물리적 초 수가 되게 하려는 목적이 있음
      그래도 MST가 이미 UTC의 기능인 만큼, 그걸 제거하는 건 우스워 보임
    • 이상적인 세계라면 컴퓨터 시스템은 시간 추적에 TAI를 쓰고, TZ 데이터베이스를 이용해 UTC나 로컬 시간으로 변환했어야 함
      하지만 현실에서는 많은 시스템이 잘못된 선택을 했고, 특히 UNIX가 가장 큰 원인임. 그 선택이 수많은 시스템과 규정에 깊이 박혀서 “그냥 TAI로 전환”하는 건 사실상 불가능함
      그래서 UTC를 “새로운 TAI”로 재해석하는 편이 더 쉬움. 언젠가 예전 UTC가 다른 이름으로 다시 등장해도 놀랍지 않을 듯함
    • TAI라는 별도 실체가 있는 게 아님. UTC에서 출발해 관심 있는 윤초 개수를 빼면 얻는 것이 TAI임. TAI가 별개의 표준 수량으로 유지되는 것은 아님
      대부분 또는 모든 나라에서 민간 시간은 UTC를 기반으로 함. 약간 더 순수하다는 이유로 전 세계 시계를 30초쯤 뒤로 돌릴 일은 없음
      GPS 시간도 TAI와 오프셋이 있지만 아무도 크게 신경 쓰지 않음. Unix epoch도 마찬가지고, 결과가 일관되면 충분함
    • 해킹은 말 그대로 사소함. 한 달에 한 번 UTC # ET인지 확인하고, 다르면 Leap_Second라는 파일을 만들면 됨. 매달 이 파일이 있는지 보고, 있으면 삭제한 뒤 Leap_Seconds 파일 값에 1을 더하고 LSSE라는 백업을 만들면 됨
      “You are not expected to understand this.” 두 시스템을 모두 유지하는 방식임. 원하면 해시나 조회 테이블로도 만들 수 있음
  • 현대적인 UTC epoch는 1972년 1월 1일이라는 점도 중요함. 그 전에는 UTC가 TAI와 다른 초 길이를 사용했음
    1971년 말 중간 단계로 정확히 0.107758 TAI초의 마지막 불규칙 점프가 있었고, 1958~1971년 UTC 또는 TAI의 작은 시간 단계와 주파수 조정 합계가 정확히 10초가 되도록 맞춰짐. 그래서 1972년 1월 1일 00:00:00 UTC는 정확히 1972년 1월 1일 00:00:10 TAI였고, 그 이후로는 정수 초 차이가 됨
    동시에 UTC의 틱 속도는 TAI와 정확히 같아졌고, UTC는 UT2가 아니라 UT1을 추적하기 시작함. 따라서 1970년과 1971년의 Unix 시간은 실제 그 시기의 UTC 시간과 일치하지 않음
    https://en.wikipedia.org/wiki/Coordinated_Universal_Time#His...
    https://en.wikipedia.org/wiki/Unix_time#UTC_basis

    • 이 때문에 오늘날 살아 있는 사람 중에는 자신의 정확한 나이(초 단위) 를 알 수 없고 앞으로도 알 수 없는 사람이 있음
      출생증명서의 시간이 초 단위로 정확하다고 가정해도 그렇다. 그 사람 생애 일부 동안 “1초의 길이”로 간주된 값이, 지금 우리가 보통 생각하는 1초와 비교해 꽤 달랐기 때문임
      여기서 초는 세슘-133 원자의 섭동 없는 바닥상태 초미세 전이 주파수 9,192,631,770/s 기준의 초를 뜻함
  • 최근 어떤 거래소용 코드를 작성했는데, 그 시스템은 VAX 또는 정확히는 OpenVMS 위에서 돌고 epoch가 1858년 11월 17일이었음
    경력 중 Unix가 아닌 epoch를 본 건 처음이었고, 다행히 사용하던 코드에서는 Unix epoch로 추상화되어 있었음

    • 1858년 epoch는 천문학 표준 달력인 Julian Day에서 온 듯함. 여기서 0일은 기원전 4713년임
      https://www.slac.stanford.edu/~rkj/crazytime.txt
      1950년대 컴퓨터 메모리에 이 날짜들을 맞추기 위해 달력을 240만 일만큼 오프셋했고, 그 결과 0일이 1858년 11월 17일이 됨
    • Excel의 epoch인 1900년 1월 1일과 Basic의 1899년 12월 31일 충돌에 관한 오래된 Microsoft 일화도 있음
      https://www.joelonsoftware.com/2006/06/16/my-first-billg-rev...
    • 알아둘 만한 또 다른 흔한 컴퓨팅 시스템으로, Windows epoch는 1601년 1월 1일임
    • 클래식 MacOS, Apple의 HFS 파일 시스템(OS X에서도 사용), PalmOS는 모두 epoch가 1904년 1월 1일이었음
      macOS/Swift Foundation API NSDate.timeIntervalSinceReferenceDate는 2001년 1월 1일을 epoch로 사용함
      Wikipedia에 유용한 목록도 있음: https://en.wikipedia.org/wiki/Epoch_(computing)#Notable_epoc...
    • PostgreSQL은 내부적으로 타임스탬프 저장에 2000-01-01 epoch를 사용함
  • 어떤 시점은 POSIX 타임스탬프로 표현할 수 없고, 어떤 POSIX 타임스탬프는 실제 시간에 대응하지 않게 됨

    • 실제 시간에 대응하지 않는 POSIX 타임스탬프가 무엇인지 궁금함. 아니면 미래에 음의 윤초가 생길 경우를 말하는 건가?
    • 이건 항상 그랬음. Unix 시간에서 1970년 이전은 정의되어 있지 않음
    • 그래도 적어도 하나의 POSIX 타임스탬프가 둘 이상의 실제 시점에 대응하지는 않음. 사람들이 모든 것에 쓰는 한 가지 표현 방식보다는 나음
    • 그렇지 않음
      그건 ISO 8601 연도가 없는 시점이 있다고 말하는 것과 비슷함. 모든 시점에는 연도가 있지만, 어떤 연도는 다른 연도보다 길 뿐임
      https://time.is/UTC를 앉아서 보고 있으면 시간은 단조롭게 증가할 것이고, 가끔 어떤 초가 아주 약간 길어질 뿐임. 예를 들면 24시간 동안 0.001% 정도 더 길어지는 식임
  • 데이터베이스에 날짜를 저장할 때 항상 Unix epoch 시간으로 저장하고, 날짜 필드에는 시간대 정보를 기록하지 않음. 시간대를 알아야 하는 요구가 있으면 별도 저장함
    대신 타임스탬프를 TAI 형식으로 저장하고, 필요할 때 UTC로 변환하는 함수를 써서 지구 관련 보정이 필요할 때 처리할 수 있게 해야 하는지 궁금함
    시간대가 지뢰밭이라는 건 알고 있지만, 그것도 시간대 경계가 시간이 지나며 바뀌는 인간의 구성물임. 절대시간에 고정한 뒤 필요할 때 원하는 로컬 시간 형식으로 렌더링해야 할 것 같음

    • 맞음. TAI 또는 유사한 형식이 “시스템” 시간을 추적하는 유일하게 합리적인 방식이고, 더 높은 수준의 시스템이 이를 사람이 보는 시간으로 변환해야 함
      윤초 조정은 시간대 변환과 같은 위치에서 일어나야 함. 안타깝게도 Unix가 잘못된 것을 표준화했고, 마이그레이션은 어려움
    • 대체로 아니고, 거의 항상 아님. 대부분의 소프트웨어는 윤초를 덮어 처리하도록 작성되어 있고, 실제로는 시계 동기화 계층에서만 발생함. 예를 들어 chrony는 윤초 스미어링을 구현함
      따라서 모든 시계는 어쨌든 UTC에 맞춰져 있음. 저장할 때 UTC에서 TAI로 변환하고, 읽을 때 다시 되돌려야 해서 엉망이 될 것임
    • “날짜 필드에 시간대 정보를 기록하지 않는다”는 부분에 대해, 실제로 타임스탬프 컬럼에 시간대 보존을 가능하게 하는 데이터베이스는 매우 적음
      보통 데이터베이스는 저장된 타임스탬프에 대한 시간대 개념이 없거나(SQL Server), “시간대 인식” 타임스탬프 타입을 제공하지만 입력을 UTC로 변환하고 원래 시간대는 버림(MySQL, Postgres)
      알고 있는 한 Oracle만 with time zone 타입에서 로컬이 아닌 시간대를 실제로 왕복 보존할 수 있음
    • 시스템이 무엇을 저장하느냐에 따라 다름. 대부분의 시스템은 몇 년에 한 번 1초 틀리는 걸 신경 쓰지 않음
      어떤 계산에서는 1초 차이가 큰 문제임. 가장 널리 쓰이는 형식이 아닌 것을 채택할 때는 조심해야 하고, 표준에서 벗어날 타당한 이유가 있어야 함. 단지 다르다는 사실만으로도 비용이 커질 수 있음
    • 데이터베이스의 네이티브 날짜-시간 필드를 쓰면 됨
  • 이 글 때문에 크리스마스가 망한 느낌임. 신성한 건 아무것도 없나? 초는 epoch 이후의 초여야 함
    태양일에서 조금 벗어나는 걸 왜 신경 써야 하는지 모르겠음. epoch 이후 초를 날짜 표현으로 바꾸는 변환기가 보정을 책임지면 되는 것 아닌가?

    • 지금 방식이 실제로 우리가 원하는 방식임. 86400초 = 1일이고, 우리는 UTC 자정이 항상 86400의 배수라는 가정 아래 동작함
      모든 소프트웨어가 윤초 도입을 하드코딩하고, 스미어링을 처리하고, 새 윤초가 도입될 때 한 달 안에 업데이트 방법을 요구하게 만들고 싶지는 않음
      지금까지 걱정하거나 생각하지 않아도 됐고, 앞으로도 그럴 필요 없음. 올바른 방식으로 처리되고 있음
  • 윤초는 적도에 장착한 대형 로켓으로 대체해야 함. 시계를 조정하지 말고 행성을 조정하자

    • 계산 실수로 지구가 너무 느려지거나 빨라지면 별로 웃기지 않을 듯함
      이슬람 전통의 종말과 적그리스도(Dajjal)에 관한 이야기에도 이런 일이 실제로 벌어지는 식의 대목이 있음. “적그리스도의 첫날은 1년 같고, 둘째 날은 한 달 같고, 셋째 날은 한 주 같을 것”이라고 하는데, 많은 이들은 이를 문자 그대로, 즉 지구 자전이 실제로 느려지고 결국 방향이 뒤집혀 해가 서쪽에서 뜨는 우주적 사건으로 받아들임. 그것이 인류 종말의 마지막 징조임
  • 윤초 때문에 epoch가 date +%s가 암시하는 것보다 29초 더 오래전이 된다고 해도 무슨 상관인가 싶음
    현재 시간을 나타내는 어떤 숫자 N에 모두가 합의한다는 사실이 훨씬 중요함. 가상의 -29초가 현실 세계에 영향을 주지는 않음. 30년 전 목표물을 대상으로 미사일 조준 루틴을 돌릴 것도 아니지 않나
    윤초 폐지에는 찬성하지만, 시간 불일치를 강조하는 게 유용하다고 보진 않음. 따지고 보면 맞는 말이어도 그렇다

    • 짧은 사건의 지속 시간을 시작/종료 시각으로 계산하는 상황을 상상할 수 있음. 그 구간이 윤초를 걸치면 타임스탬프 처리 방식에 따라 지속 시간이 꽤 달라질 수 있음
      더 중요한 건 미래에 미치는 영향임. 과거 타임스탬프가 단순한 “현재 - N초” 계산과 몇 초 다를 수 있다는 건 대부분 흥미로운 사실에 가깝지만, 미래 어느 시점에 모든 시계가 또 1초 이동해야 할 수 있다는 건 더 중요함. 이를 고려하려면 상당한 노력이 필요한 현실 사례가 많음
    • 몇몇 것에는 중요함. 그런 가상의 윤초가 없으면, 예를 들어 지역 정오에 태양 위치가 29초만큼 어긋나게 됨