업로드 없음, 100% 로컬, 계정 없음

아티클

Unix 타임스탬프와 cron 표현식 설명

Unix 타임스탬프는 그냥 정수입니다. cron 표현식은 그냥 다섯 개의 필드입니다. 둘 다 백엔드 작업에서 끊임없이 등장하며, 둘 다 예측 가능한 방식으로 사람들을 혼동시킵니다. 하나는 시간대 때문에, 다른 하나는 단위 때문에.

Unix 타임스탬프란 무엇인가

Unix 타임스탬프는 Unix epoch로 알려진 기준점인 1970-01-01 00:00:00 UTC 이후 경과된 초 수를 계산합니다. 이 정의에는 두 가지 중요한 결과가 있습니다. 첫째, 카운트는 UTC입니다. 숫자 자체에는 시간대가 포함되어 있지 않습니다. 1718400000은 기계가 어디에 있든 지구 어디서나 동일한 순간을 의미합니다. 둘째, epoch은 초 단위로 정의됩니다. 다른 단위가 아닙니다. 1718400000 같은 값은 시스템이나 프로토콜이 명시적으로 다른 선택을 하지 않는 한 항상 1970년 1월 1일 UTC 자정 이후의 초입니다. 타임스탬프는 설계상 시간대에 종속되지 않으며, 그것이 바로 서로 다른 지역의 시계가 모호하지 않게 같은 순간을 참조해야 하는 로그, 데이터베이스, 시스템 간 통신에 유용한 이유입니다.

왼쪽에 1970-01-01 00:00:00 UTC의 Unix epoch, 중간에 현재 타임스탬프, 오른쪽에 32-bit 부호 있는 정수 최대값으로 표시된 2038 오버플로우 경계를 보여주는 타임라인.

초, 밀리초, 2038 문제

많은 현대 런타임과 API는 초 대신 밀리초를 사용합니다. JavaScript의 Date.now()는 밀리초를 반환하므로 1718400000000은 초 정밀도 값 1718400000과 같은 순간입니다. 낯선 타임스탬프를 받을 때 크기가 단위를 알려줍니다. 10자리 숫자는 거의 항상 초이고, 13자리 숫자는 거의 항상 밀리초입니다. 2038 문제는 다른 선택에서 비롯됩니다. 초 정밀도 타임스탬프를 부호 있는 32-bit 정수에 저장하는 것입니다. 부호 있는 32-bit 정수의 최대값은 2147483647로, 2038-01-19 03:14:07 UTC에 해당합니다. 그 초 이후 카운터는 큰 음수로 오버플로우되고, 이 경계를 처리하지 않는 시스템에서는 날짜가 1901년으로 롤백됩니다. 수정책은 64-bit 저장소를 사용하는 것입니다. 대부분의 현재 운영 체제와 데이터베이스는 이미 그렇게 합니다. 그러나 수십 년 전에 필드 너비를 고정한 임베디드 시스템, 네트워크 장치, 이전 파일 형식은 여전히 위험합니다.

epoch를 사람이 읽을 수 있는 날짜로 변환: 시간대 단계

epoch 값을 읽을 수 있는 날짜로 변환하려면 두 단계가 필요합니다. 정수에서 UTC 날짜 구성 요소를 검색한 다음 UTC 오프셋을 적용하여 현지 시간을 구합니다. 타임스탬프 자체는 UTC입니다. 1718325000이 어떤 날짜를 나타내는지 물으면 올바른 답은 UTC 기준 2024-06-14 00:30입니다. 뉴욕(여름 UTC-4)에서 같은 초는 하루 전날인 2024-06-13 20:30에 해당합니다. 시각뿐 아니라 날짜 자체가 바뀝니다. 이것이 이 단계를 건너뛸 때 잘못된 결과가 나타나는 이유입니다. 개발자가 UTC로 원시 타임스탬프를 기록하고, 보고 도구가 변환 없이 현지 시간으로 렌더링하면 날짜가 몇 시간 또는 하루 어긋난 것처럼 보입니다. Sunasty의 timestamp-converter 도구는 이것을 명시적으로 처리합니다. epoch 값을 입력하면 UTC 날짜와 시간을 기기의 현지 날짜와 시간 옆에 나란히 표시하므로, 이런 날짜 경계 이동을 한눈에 확인할 수 있습니다. 변환은 브라우저에서 완전히 실행되며 붙여넣은 내용은 어디에도 전송되지 않습니다.

같은 epoch 값에 대한 두 개의 달력 격자를 나란히 배치한 그림. UTC 격자는 특정 하루를 강조하고, 뉴욕(UTC-4) 격자는 그 전날을 강조하여 시차로 인해 현지 날짜가 하루 앞으로 당겨지는 모습을 보여준다.

Cron 구문: 다섯 개의 필드, 범위, 단계, 목록

cron 표현식은 Unix 계열 시스템에서 반복 작업을 예약합니다. 표준 구문은 공백으로 구분된 다섯 개의 필드를 가집니다. 분(0-59), 시(0-23), 일(1-31), 월(1-12), 요일(0-7, 0과 7 모두 일요일을 나타냄). 필드의 별표(*)는 "모든 유효한 값"을 의미합니다. 표현식 30 8 * * 1-5는 월요일부터 금요일까지 08:30에 실행됩니다. 범위는 하이픈을 사용합니다. 1-5는 값 1, 2, 3, 4, 5를 포함합니다. 목록은 쉼표를 사용합니다. 1,15는 1일과 15일을 의미합니다. 단계는 슬래시를 사용합니다. 분 필드의 */15는 15분마다(0, 15, 30, 45)를 의미합니다. 이 결합자들은 함께 사용할 수 있습니다. 0-30/10은 0, 10, 20, 30을 의미합니다. cron에 없는 것은 시간대 필드입니다. 데몬은 실행 중인 기계의 시계를 읽으며, 이 시계는 서버의 현지 시간대로 설정됩니다. 서버가 UTC에서 실행되지만 개발자가 현지 시간을 기대한다면, 일정이 잘못된 시간에 실행됩니다. 실용적인 규칙은 cron 일정을 서버-현지-시간 표현식으로 취급하고 cron 라인 옆에 서버의 시간대를 문서화하는 것입니다.

로컬에서 timestamp-converter 사용하기

Sunasty의 timestamp-converter는 양방향으로 변환합니다. epoch에서 사람이 읽을 수 있는 날짜로, 그리고 사람이 읽을 수 있는 날짜에서 epoch로. 초 정밀도 값이나 밀리초 정밀도 값을 입력할 수 있으며, 도구가 크기에서 단위를 감지합니다. 결과는 UTC와 기기의 현지 시간대를 나란히 보여주며, 복사하기 편하도록 초와 밀리초 원시 값도 함께 표시합니다. Now 버튼을 누르면 현재 타임스탬프가 한 번에 채워지므로 터미널을 열지 않고 현재 Unix 시간을 빠르게 확인할 수 있습니다. 별도의 시간대 선택기는 없습니다. 현지 시간 열은 항상 브라우저에 현재 설정된 시간대를 반영합니다. 이 모든 것이 브라우저에서 실행됩니다. 필드에 붙여넣은 값은 클라이언트 측 JavaScript에서 읽히며 기기를 떠나지 않습니다.

이 아티클의 도구

자주 묻는 질문

JavaScript는 왜 초 대신 밀리초를 사용하나요?

JavaScript의 Date 객체는 처음부터 밀리초 미만 정밀도로 작동하도록 설계되었으며, 밀리초는 소수점 없이 초의 1000배 해상도를 제공합니다. 그 대신 값이 더 크며, 이것이 Date.now()가 13자리 숫자를 생성하는 반면 대부분의 서버 측 타임스탬프는 10자리인 이유입니다.

cron을 실행하는 모든 서버가 UTC에 있어야 하나요?

아닙니다. 하지만 서버를 UTC에서 실행하는 것은 바로 모호함을 없애기 때문에 일반적인 관행입니다. 서버가 UTC에 있으면 0 2 * * *와 같은 cron 표현식은 02:00 UTC를 의미하며 그 시간은 연중 내내 안정적입니다. DST를 관찰하는 시간대의 서버에서는 같은 작업이 여름과 겨울에 다른 UTC 순간에 실행되며, 시계 변경 경계에서 두 번 실행되거나 한 번 건너뛸 수 있습니다.

2038 이후의 타임스탬프를 위한 안전한 저장 유형은 무엇인가요?

부호 있는 64-bit 정수는 초 정밀도 타임스탬프를 연도 292277026596까지 보유하며, 이는 어떤 실용적인 관심사를 훨씬 넘습니다. 대부분의 현재 데이터베이스는 기본적으로 타임스탬프를 64-bit 값으로 저장합니다. 32-bit 필드를 사용하는 레거시 스키마나 바이너리 파일 형식으로 작업 중이라면 2038 경계 이전에 64-bit 저장소로 마이그레이션하는 것이 올바른 수정입니다.