나는 최근 UNIX Time에 관해 많은 것을 읽었는데, 그 중 대부분은 일관되지 않고 모순적이었습니다. UNIX Time(이하 UXT), TAI, UTC 간의 변환을 조정하려고 하는데 이를 위해서는 UXT를 올바르게 이해해야 합니다. 문제는 이 일을 하는 다른 사람을 찾을 수 없다는 것입니다.
다음은 힘든 연구를 통해 수많은 출처에서 재구성된 최선의 설명입니다. 뭔가 잘못된 것도 있습니다. 다음에 대한 종합적인 분석과 점별 검증/반박을 구하고 있습니다. 기본적으로 제대로 작동하려면 다음을 수정하세요.
TAI는 단조 증가하는 시간 표준입니다. SI 초 단위로 측정되며 DST와 윤초를 무시합니다.
UTC는 TAI와 동일하지만 천문시 기준 UT1의 0.9SI초 이내가 되도록 정수 윤 SI초(60초로 반영되는 시간 문자열로 변환)로 수정됩니다.
UXT는 개수입니다.UNIX 초1970년 1월 1일 00:00:00 UTC부터. 하루는 항상 정확히 86400초입니다. 그러나 UXT는 UTC와 관련이 있습니다.
어떻게 이럴 수있어? 훌륭한,UNIX 초는 SI 초와 달라야 합니다., 윤초는 완전히 규칙적이지 않기 때문에 UNIX 초는 잘 정의된 시간 길이가 될 수 없습니다.
UTC에서 UXT로 변환UNIX 사양 섹션 4.15다른 UTC 시간을 동일한 UXT 타임스탬프에 별칭으로 지정합니다.UNIX 초를 SI 초와 효과적으로 동일하게 만듭니다(2개의 SI 초인 UNIX 윤초 제외)..
실제로 실제로 일어나는 일은 다양합니다. 대부분의 컴퓨터는 원격 서버를 기반으로 동기화하므로 동기화 중에 윤초 업데이트를 암시적으로 처리합니다.이 모든 의미는 각 개별 UXT 타임스탬프를 UTC로 쉽게 변환할 수 있다는 것입니다(다음을 사용).
gmtime
또는 각각 §4.15), 아무것도 알아내기 위해 산술을 수행하는 데 실제로 사용할 수는 없습니다. 특히,difftime
UNIX 초를 반환합니다., 따라서 관련 윤초가 모두 어디에 있는지 알지 않는 한 다른 타임스탬프에 추가하는 것을 포함하여 아무 것도 할 수 없습니다.
여기까지는 이해한 것 같아요.
- 하지만 이제 실제 코드를 보면 이러한 작업이 전혀 수행되지 않습니다. 나는 사람들이 측정된 기간을 사용
difftime
하고 그것이 충분히 좋기를 바라고(또는 문제가 있다는 것을 모르고) 이해할 수 있지만 타이밍 라이브러리도 잘못되었습니다.
예로서,libtai
tai_now.c:7
다음과 같이 UXT에서 TAI( )로의 변환을 제공합니다TAI := 4,611,686,018,427,387,914 + UXT
. TAI는 SI 초를 계산하고 UXT는 UNIX 초를 계산하므로 이 작업을 수행할 수 없습니다. 그러나libtai
윤초는 명시적으로 처리되므로 이것이 부주의한 오류라고 보는 것은 합리적이지 않습니다.
에 국한된 것은 아닙니다libtai
. 이런 현상은 어디에서나 볼 수 있습니다.
따라서 포인트 1-6은 포인트 7과 일치하지 않습니다. 즉, 기존 코드의 상당수는 그것이 나타내는 시간적 기준과 모순됩니다. 무엇이 잘못되었나요?
답변1
문제는 대부분의 문서가 모호한 문장 없이 시간 척도를 구분할 수 있는 어휘를 사용하지 않는다는 점이다. 나는 추천한다http://www.ucolick.org/~sla/leapsecs/picktwo.html이 문제에 대한 소개로서, 역사적 사용법에는 서로 관련되지 않은 두 가지 종류의 초가 있습니다. 하나는 지구 거주자의 달력일 세분화이고 다른 하나는 특정 기준 프레임에서 측정된 일정한 기간입니다. 1970년 전후의 날짜에 걸쳐 있는 모든 시간 라이브러리는 두 초를 모두 활용하려고 시도하여 궁극적으로 arcsin(-2)을 제공한다고 주장하는 함수와 유사한 답변을 제공합니다. 중요한.
답변2
훌륭한. . . 당신의 미래의 자아는 여기에 있으며, 종결감을 위해 글을 쓰고 있습니다.
당신이 이 질문을 쓴 지 몇 년이 지났지만, 오늘이 되기 몇 년 전, 당신은 이렇게 썼습니다.거대한 튜토리얼이로써 문제가 해결되었습니다. 이는 TAI부터 UTC, 오프셋 및 UXT까지 현대 시간 표준에 대한 완전한 가이드로 구성됩니다.
귀하의 질문에 관해서는 1-6번 항목이 실제로 기본적으로 올바른 것 같습니다. 귀하의 요점 7은 "소프트웨어불가능한정말 못해요, 그렇죠? "
스포일러 경고:그것은 할 수 있다. libtai에 대한 구체적인 불만 사항은 좋은 예가 아닙니다. 라이브러리에는 윤초가 포함되어 있지만 보고 있는 단일 기능뿐만 아니라 적절한 기능을 결합해야만 합니다. 우리에게 이것은 엄청난 (그리고 분명히 혼란스러운) 결함처럼 느껴지며, 그것이 정답이 되더라도(그렇다면 누가 알겠습니까), 이런 종류의 일은 매우 흔하기 때문에 그것에 대해 하프문을 하는 것은 소용이 없습니다. 대부분의 소프트웨어는 실제로 문제가 발생할 뿐만 아니라 소프트웨어는 서로 다른 호환되지 않는 방식으로 문제가 발생합니다!
이런,문서기본 UXT 프리미티브의 경우 time(...)
명확하지 않습니다. 표준 C 문서(인용하다),(인용하다), POSIX 표준 준수(일부)(인용하다)이것이 epoch 이후의 초 수라고 가정해 보겠습니다. 하지만 POSIX 표준의 다른 곳에서는(인용하다), 이는 초 수가 아니라 에포크 이후의 초 수입니다.윤초 제외, 이는 올바른 표현입니다. 계산을 더 쉽게 하려는 의도이지만 뺄셈 때문에 계산이 더 어려워지는 것은 분명합니다.작동하지 않습니다수직선에 불연속성을 도입할 때. difftime(...)
예를 들어, 사용된 모든 절차는 부정확할 수 있습니다.
여기서 핵심 정신 모델은 SI 초와 UNIX 초가 다르다는 것입니다. 이는 POSIX 사양의 다른 부분에서 가장 명확합니다.(인용하다). 이 섹션에서는 날짜-시간 변환을 통해 UXT를 UTC로 연결합니다. UTC에는 윤초가 포함되어 있지만 이 섹션은반품지정된 날짜의 길이는 86,400초입니다. 우리는 이것을 어떻게 조화시킬 수 있습니까? 중요한 깨달음은 일부 UNIX 초의 길이가 2SI 초이고 일부는 0(분명히 대부분은 1임)이라는 것입니다. 아직도 혼란스러워요? 가서 튜토리얼을 읽어보세요! 실제 코드가 너무 지저분한 것은 당연합니다.
불행히도 코딩을 통해 독자를 안내할 수는 없습니다. 자신만의 타이밍 라이브러리를 작성했지만 이는 복잡하고 강력하며 아직 실제로 생산할 준비가 되어 있지 않습니다.
time(...)
먼저 POSIX 에포크 상대 수인 UNIX 초를 가져오고 220 924 790을 뺀 다음 (테이블에서) 윤초를 추가하여 SI 초의 TAI 에포크 상대 수를 가져오는 호출을 하고 싶습니다 . 복귀하려면 역순으로 실행하세요. (참고: TAI 시대는 약간 모호합니다. 저는 1977-01-01 00:00:00 TAI(예: 1976-12-31 23:59:45 UTC)를 선택했습니다. 이는 표준화된 TAI인 JD TAI 의 시대이기 때문입니다 . TCB, TCG, TT 및 TDB(인용하다).)
C++20에서는std::chrono::tai_clock
, 시대는 1958-01-01 00:00:00 TAI(즉, 1957-12-31 23:59:50 UTC)입니다. 바라건대 이것이 정확하고 우리는 이 모든 추악한 일을 우리 뒤에 놓을 수 있습니다.
답변3
당신 말이 맞아요. 이 혼란은 끔찍해요. 내 결론:
UXT는 윤초 동안을 제외하고 UTC와 동일합니다. 여기서 UTC는 60까지 계산되고 UTX는 1초 동안 "멈춥니다".
답변4
정신 건강을 위한 가장 좋은 방법은 하루에 예외 없이 86,400초가 있다고 가정하는 것입니다. 이는 대부분의 사람들에게 충분한 시간입니다. 지금 시간을 계산해서 5,000 x 86,400초를 빼면 5,000일 전과 정확히 똑같은 시, 분, 초가 나옵니다.
Posix 시간은 이제 UTC이지만 윤초가 제거되었습니다. 즉, 항상 UT1(태양시)에 매우 가깝고 최대 0.9초 차이가 납니다. 가장 좋은 정신 모델은 윤초가 UTC에 추가되거나 제거될 때마다 Posix 시간으로 2초 길이의 초가 되거나 0초 길이의 초가 된다는 것입니다. 윤초가 발생하는 정확한 순간에 스톱워치를 사용하면 Posix에 따르면 스톱워치에 따라 특정 분은 61초 또는 59초가 소요됩니다. 또는 컴퓨터에 초가 표시된 시계가 표시되면 초 숫자는 1초 동안 가만히 있거나 어떤 지점에서 2초 동안 점프합니다. 윤초가 제거되는 순간 외에는 이를 관찰할 수 없습니다. Posix 시스템에는 이러한 변경 사항에 대한 흔적이 없습니다.
이게 언제 잘못된 건가요? 적절한 시간에 100m 경주가 있고 시작 및 종료 시간을 Posix 시간에 따라 기록하면 누군가는 시작 후 9.317초에 경주를 완료할 수 있습니다. 실제로는 10.317초가 됩니다. 따라서 실제 데이터가 있는 경우 시간 간격이 1초씩 어긋날 수 있습니다.
어떻게 해결할 수 있나요? 이 문제를 해결할 수 있는 유일한 방법은 윤초를 삽입하는 테이블을 만들어 이를 이용해 "윤초 없는 UTC"를 TAI로 바꾸는 것이다.
Posix 시간은 그렇지 않습니다.진짜UTC에는 윤초가 없지만 시스템에는 UTC에 대한 최상의 정보가 있습니다. 컴퓨터의 시계를 "수동으로" 변경할 수 있으며 Posix 시간은 꺼집니다. 컴퓨터의 시계는 다소 부정확할 수 있으며 시간 서버에 의해 수정될 수 있습니다. 이 경우 다시 수정되기 전에 하루에 2초씩 UTC에서 벗어날 수 있습니다.
이 문제가 있는 앱이 있는데 iOS(보통 Posix에 있음)에 시작 시간을 반환하는 sysctl 호출이 있습니다. 시계가 변경되면 이 함수는 변경된 모든 초를 제외하고 변경된 날짜를 반환합니다. 컴퓨터를 다시 시작하면 변경된 날짜도 반환됩니다. 따라서 마지막으로 알려진 값을 저장하고 부팅 시간이 변경되면 시간 서버에 문의할 수 있습니다.