clock — 날짜와 시간 다루기
clock — 날짜와 시간 다루기
날짜와 시간을 얻고, 조작하고, 원하는 형식으로 표시하는 일은 프로그램에서 빠질 수 없는 부분이에요. clock 명령은 초·밀리초·마이크로초 단위의 시간 처리, 시간 형식화, 문자열 시간 파싱을 서브명령 형태로 모두 제공합니다.
본문
clock 명령은 시간을 나타내는 값을 얻고 조작하는 여러 작업을 수행합니다.
clock add timeVal ?count unit...? ?-option value?
(음수일 수도 있는) 오프셋을 정수 초로 표현된 시간에 더합니다. CLOCK ARITHMETIC 참조.
clock clicks ?-option?
-option 인자가 없으면 시스템 종속 정수 값으로 고해상도 시간 값을 리턴합니다. 값의 단위는 시스템 종속이지만 CPU 사이클 카운터처럼 시스템에서 가장 높은 해상도의 클록이어야 해요. -milliseconds면 clock milliseconds와 동의어, -microseconds면 clock microseconds와 동의어입니다(둘 다 구식 사용법). HIGH RESOLUTION TIMERS 참조.
clock format timeVal ?-option value...?
정수 초로 표현된 시간을 사용자나 외부 프로그램용 형식으로 형식화합니다. FORMATTING TIMES 참조.
clock microseconds
현재 시간을 정수 마이크로초 수로 리턴합니다.
clock milliseconds
현재 시간을 정수 밀리초 수로 리턴합니다.
clock scan inputString ?-option value...?
문자열로 표현된 시간을 스캔해 정수 초 수를 만듭니다. SCANNING TIMES 참조.
clock seconds
현재 시간을 정수 초 수로 리턴합니다.
파라미터와 옵션
- count — 어떤 시간 단위의 수를 나타내는 정수.
- timeVal — 에포크 시간(1970년 1월 1일 00:00 UTC)으로부터의 초 수로 표현된 절대 시간. 초 수에 윤초(leap second)는 포함되지 않아요. Tcl은 각 UTC 일이 정확히 86400초인 것처럼 셉니다.
- unit — seconds, minutes, hours, days, weeks, months, years 중 하나 또는 그 단어의 유일한 접두어. count와 함께 간격을 나타냅니다(예: 3 seconds, 1 year).
옵션:
- -base time — clock scan에 있는 상대 시간이 time에 상대적임을 지정. time은 에포크 1970-01-01 00:00 UTC로부터의 명목 초 수.
- -format format — clock format의 출력 또는 clock scan의 예상 입력 형식. 형식 문자열은 퍼센트 기호("%") 외의 문자들 사이에 퍼센트 기호로 시작하는 두 문자 시퀀스(format group)들을 섞어 이룹니다. clock format의 기본 형식은
%a %b %d %H:%M:%S %Z %Y이고, clock scan에서 -format이 없으면 "자유 형식 스캔"을 요청합니다. - -gmt boolean — true면 clock add·clock format·clock scan에 지정된 시간을 UTC로 처리. false면 로컬 시간대. 구식 사용법이며, 올바른 최신 사용은 "-timezone :UTC"로 UTC 시간대를 지정하는 것.
- -locale localeName — 로케일 의존 스캔·형식화(및 그레고리력 채택 이전 날짜의 날짜 연산)를 localeName 로케일로 수행. msgcat 패키지가 받는 로케일이거나 특수 이름 system(프로세스 현재 로케일) 또는 빈 문자열(Tcl 기본 로케일).
- -timezone zoneName — 클록 연산·형식화·스캔을 zoneName 시간대 규칙대로 수행. 기본은 현재 시간대이며, 우선순위로 TCL_TZ 환경 변수 → TZ 환경 변수 → Windows의 제어판 시간대 설정 → C localtime·mktime 함수 순으로 결정돼요.
CLOCK ARITHMETIC (시간 연산)
clock add 명령은 첫 인자의 값(에포크 1970-01-01 00:00 UTC로부터의 명목 초)에 대해 시간 연산을 수행합니다. 나머지 인자들(-timezone, -locale, -gmt 옵션 제외)은 정수와 키워드가 번갈아 나오며, 키워드는 seconds, minutes, hours, days, weeks, months, years 또는 그 유일한 접두어에서 고릅니다.
초·분·시간의 덧셈은 비교적 직관적이에요. 주어진 시간 증가분(분은 60배, 시는 3600배)을 timeVal에 더하고 결과를 에포크로부터의 명목 초로 해석합니다. 윤초가 삽입·제거되는 지점을 지나면 놀라운 결과가 나올 수 있는데, clock add는 윤초를 그냥 무시하고 시간이 23:59:58, 23:59:59, 00:00:00 순서로 온다고 가정합니다. Tcl의 시간 모델은 이 가정을 윤초에 반응해 클록을 미세하게 빨리/느리게 조정해 다시 맞추는 방식으로 처리해요.
시간을 더하고 빼는 것은 절대 시간 단위로 정의되므로, 서머타임(DST)을 관찰하는 시간대에서 고정된 시간량을 더하게 됩니다. 예를 들어 다음 코드는 그 구간에 클록이 바뀌었기 때문에 x를 04:00:00으로 설정해요:
set s [clock scan {2004-10-30 05:00:00} \
-format {%Y-%m-%d %H:%M:%S} \
-timezone :America/New_York]
set a [clock add $s 24 hours -timezone :America/New_York]
set x [clock format $a \
-format {%H:%M:%S} -timezone :America/New_York]
일·주를 더하고 빼는 것은 해당 시간을 적절한 시간대·로케일의 달력 일과 시간으로 변환해 수행합니다. 필요한 일 수(주는 7을 곱해 일로 전환)를 달력 일에 더하고 다시 에포크 초 수로 변환해요. 서머타임이 시작·끝나는 시간 변경 지점을 건너 일 수를 더하거나 빼면 그 날의 같은 로컬 시간이 결과가 됩니다. 예를 들어 다음은 x를 05:00:00으로 설정합니다:
set s [clock scan {2004-10-30 05:00:00} \
-format {%Y-%m-%d %H:%M:%S} \
-timezone :America/New_York]
set a [clock add $s 1 day -timezone :America/New_York]
set x [clock format $a \
-format {%H:%M:%S} -timezone :America/New_York]
같은 로컬 시간이 같은 날 두 번 발생하는 모호한 경우엔 더 이른 시간을 써요. 변환이 불가능한 시간을 만들면(예: 미국 규칙의 봄 서머타임 변경 동안 02:30) 클록이 안 바뀐 것처럼 변환됩니다. 달력 일 수 더하기는 율리우스력↔그레고리력 변환에서도 올바르게 동작하며 생략된 날을 건너뜁니다.
개월·연도 수를 더하는 것도 비슷합니다. 결과 날짜가 그 달의 일 수가 부족해 불가능하면(예: 1월 31일에 1개월을 더할 때) 그 달의 마지막 날이 대신 사용돼요. 따라서 1월 31일에 1개월을 더하면 평년엔 2월 28일, 윤년엔 2월 29일이 됩니다. 명령에 count unit 쌍이 여러 개 있으면 왼쪽에서 오른쪽으로 순차 평가됩니다.
HIGH RESOLUTION TIMERS (고해상도 타이머)
clock 명령의 대부분 서브명령은 에포크로부터의 초 수로 표현된 시간을 다루며, 이것이 clock seconds가 리턴하는 표현이에요. 세 가지 예외가 있는데 모두 더 높은 해상도가 필요할 때 씁니다. clock milliseconds는 에포크의 밀리초 수, clock microseconds는 마이크로초 수를 리턴해요. 추가로 clock clicks는 플랫폼 종속 고해상도 타이머를 리턴하는데, clock seconds·clock milliseconds와 달리 고정 에포크에 묶여 있지 않아 상대적 시간 측정(벤치마크 등)에만 쓰입니다.
FORMATTING TIMES (시간 형식화)
clock format 명령은 사용자 표시나 외부 매체 기록용 시간을 만듭니다. 에포크 1970-01-01 00:00 UTC로부터의 초(예: clock seconds, clock scan, clock add, file atime, file mtime이 리턴)를 받아요. -format 옵션이 있으면 그 인자는 날짜·시간 형식을 지정하는 문자열이고, -timezone이 있으면 형식화할 시간대를 지정합니다. -locale이 있으면 msgcat 패키지와 같은 형식으로 시간을 형식화할 로케일을 지정하며, 기본은 현재 로케일이 아니라 루트 로케일 **{}**라는 점을 주의하세요. 현재 로케일은 -locale current로, 플랫폼이 지원하면 system 로케일로 얻을 수 있어요(Windows에선 제어판에서 사용자가 선택한 날짜·시간 형식).
SCANNING TIMES (시간 스캔)
clock scan 명령은 문자열로 형식화된 시간을 받아 에포크 1970-01-01 00:00 UTC로부터의 초 수로 변환합니다. 보통 예상 입력 형식을 설명하는 -format 옵션을 받아요. -base 옵션이 있으면 상대 시간 해석의 기준 시간이 되고, 없으면 현재 시간입니다. 고정 형식으로 시간을 스캔하는 것은 날짜, 시간대, 하루 중 시각 세 가지를 결정해 하나의 시점으로 결합하는 방식입니다. 스캔 전에 형식 문자열은 %c, %Ec, %x, %Ex, %X·%Ex, %r, %R, %T, %D, %EY, %+ 형식 그룹을 현재 로케일 적절한 대응물로 전처리합니다(예: %D는 en_US 로케일에서 %m/%d/%Y로 대체).
날짜는 전처리된 형식 문자열에 있는 필드들에 따라 결정됩니다. 우선순위로: %s(에포크 초) → %J(율리우스 일 수) → 세기·년·월·일 또는 ISO8601 회계연도·주·요일의 완전한 집합 → 세기 없는 두 자리 집합(연도는 19382037으로 추정) → 연도 완전히 없는 집합 → 요일/일만 있는 경우(주는 월요일일요일, ISO8601 방식) → 마지막으로 기준 시간의 날짜. 시간도 비슷하게 %s → 24시간제 시각 또는 12시간제+AM/PM → 미지정 시 자정(00:00). 시간대는 -timezone·-gmt 옵션이나 현재 시간대로 정해요. 형식 문자열에 %z·%Z가 없으면 하루에 두 번 나타나는 시간이 모호할 수 있는데(한 번은 DST 없이, 한 번은 포함) 이런 경우 첫 번째 발생을 선택합니다. 필드가 범위를 벗어나 불가능한 시간이 되면 그 필드 단위를 더하거나 빼서 범위로 가져옵니다(예: 그 달의 0일이면 1일에서 하루를 빼 이전 달의 마지막 날이 됩니다).
FORMAT GROUPS (형식 그룹)
clock scan과 clock format이 인식하는 형식 그룹:
- %a — 출력: 로케일의 요일 약어(예: Mon). 입력: 로케일의 요일 이름(약어·전체·유일 접두어) 매칭.
- %A — 요일 전체 이름(예: Monday).
- %b — 월 약어(예: Jan).
- %B — 월 전체 이름(예: January).
- %c — 로케일화된 날짜·시각 표현(그레고리력 기대).
- %C — 세기 번호(인도-아라비아 숫자).
- %d — 일(두 자리 십진). 입력: 한두 자리.
- %D — %m/%d/%Y와 동의어. en_US 로케일 내 데이터 교환에만 사용 권장.
- %e — 일(한두 자리, 한 자리는 앞에 공백).
- %Ec — 로케일 대체 달력의 날짜·시각 표현. %EC — 대체 달력의 시대 이름. %EE — B.C.E./ C.E. 표시. %Ex — 대체 달력의 날짜. %EX — 대체 숫자의 하루 중 시각. %Ey — 대체 달력·숫자의 시대 연도 수. %EY — 대체 달력·숫자의 연도(종종 %EC%Ey와 동의어).
- %g — 주 기반 ISO8601 달력용 두 자리 연도(%V가 만든 주 번호와 짝). %G — 같은 용도의 네 자리 연도.
- %h — %b와 동의어.
- %H — 하루의 시간(00-23) 두 자리.
- %I — 12시간제 시간(12-11) 두 자리.
- %j — 연중 일(001-366) 세 자리.
- %J — 율리우스 일 수. 1970-01-01 에포크는 율리우스 일 수 2440588에 해당.
- %k — 24시간제 시간(0-23) 한두 자리.
- %l — 12시간제 시간(12-11) 한두 자리.
- %m — 월(01-12) 정확히 두 자리.
- %M — 시의 분(00-59) 정확히 두 자리.
- %N — 월(1-12) 한두 자리(한 자리는 앞에 공백).
- %Od, %Oe, %OH, %OI, %Ok, %Ol, %Om, %OM, %OS, %Ou, %Ow, %Oy — "O" 없는 대응물과 동의어지만 문자열을 로케일 의존 대체 숫자로 만들고 파싱.
- %p — 하루 중 일부 표시 AM/PM(로케일 적절). %P — am/pm.
- %Q — Tcl 라이브러리 내부용으로 예약.
- %r — 12시간제 로케일 의존 하루 중 시각. %R — 24시간제(%H:%M). %T — %H:%M:%S와 동의어.
- %s — timeVal 인자를 십진 정수로 그대로 출력/입력하며, 다른 모든 입력 형식을 무시(unique point in time).
- %S — 시의 초(00-59) 두 자리.
- %t — TAB 문자.
- %u — 요일 번호(1→월요일, 7→일요일). 일요일은 0 또는 7 허용.
- %U — 연중 주의 서수(00-53, 연중 첫 일요일이 01주의 첫날). 구식(미국 은행권) 해석.
- %V — ISO8601 주 번호(01-53). 1월 4일을 포함하는 주(또는 4일 이상 포함하는 첫 주, 첫 목요일 포함 주). 각 주는 월요일에 시작.
- %w — 요일 서수(일요일==0, 토요일==6). %u는 ISO8601 요일 번호.
- %W — 연중 주 번호(00-53, 01주는 그 해 첫 월요일 시작). ISO8601이 아님.
- %x — 로케일 의존 날짜 표현. %X — 로케일 의존 하루 중 시각.
- %y — 세기의 두 자리 연도(1938~2037 추정). ISO8601 주 번호용이 아님(%g 사용).
- %Y — 네 자리 달력 연도. ISO8601 주 번호용이 아님(%G 사용).
- %z — 현재 시간대를 그리니치 동쪽(+hhmm)/서쪽(-hhmm)의 시·분으로 출력. 입력: 시간대 지정자.
- %Z — 현재 시간대 이름(로케일 번역 가능). 입력: 시간대 지정자. BST가 British Summer Time인지 Brazilian Standard Time인지처럼 애매하므로 보통 RFC822 날짜 파싱에만 쓰고, 컴퓨터용 문자열엔 숫자 시간대 권장.
- %% — 리터럴 "%" 문자.
- %+ — "%a %b %e %H:%M:%S %Z %Y"와 동의어.
TIME ZONES (시간대)
로컬 시간을 처리할 때 사용할 시간대의 우선순위 소스: ① %z·%Z 형식 그룹이 파싱·매칭한 문자열 내 지정 시간대, ② clock 명령의 -timezone 옵션(또는 -gmt 1), ③ TCL_TZ, ④ TZ 환경 변수, ⑤ Windows 제어판 로컬 시간대, ⑥ C 라이브러리의 로컬 시간대(mktime·localtime).
경우 ①에서만 문자열이 알려진 밀리초(미국) 약어 목록 중 하나인지 검사합니다:
gmt ut utc bst wet wat at
nft nst ndt ast adt est edt
cst cdt mst mdt pst pdt yst
ydt hst hdt cat ahst nt idlw
cet cest met mewt mest swt sst
eet eest bt it zp4 zp5 ist
zp6 wast wadt jt cct jst cast
cadt east eadt gst nzt nzst nzdt
idle
일치하면 알려진 시간대로 해석합니다. 목록에 없는 경우① 및 항상 경우②⑥는 다음 규칙이 적용돼요. 시간대가 콜론으로 시작하면 :America/New_York 같은 표준화된 위치 이름 목록 중 하나입니다. 특별히 :localtime은 C 라이브러리가 정의한 로컬 시간대를 가리켜요. 더하기/빼기 기호 뒤 네 자리 또는 여섯 자리 십진 숫자로 된 시간대 문자열은 UTC로부터의 시·분·초 오프셋으로 해석됩니다(더하기는 그리니치 동쪽). Posix TZ 환경 변수 명세에 맞는 문자열도 인식하며, DST 부분이 있지만 DST 시작·끝 규칙이 없으면 기본 규칙을 씁니다(오프셋 0+12는 유럽/러시아 규칙, 그 외는 미국 규칙). 그 밖의 문자열은 콜론을 붙여 위치 이름으로 시도합니다.
LOCALIZATION
날짜·시간 형식화·파싱의 지역화를 원하는 개발자는 https://tip.tcl-lang.org/173 명세를 참조하세요.
FREE FORM SCAN (자유 형식 스캔)
clock scan이 -format 옵션 없이 호출되면 자유 형식 스캔을 요청하며, 이 형태는 폐기(deprecated)됐어요. 이유는 모호함이 너무 많기 때문입니다("2000"이 연도인지, 하루 중 시각인지, 수량인지). 이 경우 -base·-gmt 옵션만 허용되고 -timezone·-locale은 오류예요.
레거시 코드 이해를 위해 자유 형식 해석 규칙을 요약하면: 시간만 지정하면 현재 날짜를 가정하고, 시간대 약어가 없으면 로컬 시간대를 가정합니다(-gmt true면 GMT 기준). -base는 그 값의 날짜만 사용해요. 인식하는 지정 형식은 time(hh?:mm?:ss? ?meridian? ?zone? 또는 hhmm…), date(mm/dd/yy, monthname dd, day, dd monthname yy, CCyymmdd 등), ISO 8601 point-in-time(CCyymmddThhmmss 등 네 형식만 허용), relative time(number unit — year/fortnight/month/week/day/hour/minute/second과 tomorrow/yesterday/today/now/last/this/next/ago 수정자)입니다. 2자리 연도는 00-68을 2000-2068, 69-99를 1969-1999로 처리하고, 일부 플랫폼은 38-70년을 표현 못 해 오류가 날 수 있어요.
더 알아보기
- msgcat — 로케일 처리
- 키워드: clock, date, time