Time — 하루 중 시각을 다루는 Time 구조체와 함수들
Time — 하루 중 시각을 다루는 Time 구조체와 함수들
Time는 하루 중의 시각(time of day) 을 표현하는 구조체(struct)와 관련 함수들을 제공하는 모듈이에요. Time 구조체는 hour, minute, second, microsecond 필드를 담아요.
새로운 시각은 new/4 함수로 만들거나 ~T 시길(sigil_T/2)을 써서 만들 수 있어요. 둘 다 시각 필드를 직접 접근할 수 있는 구조체를 반환해요.
iex> ~T[23:00:07.001]
~T[23:00:07.001]
iex> time = ~T[23:00:07.001]
iex> time.hour
23
iex> time.microsecond
{1000, 3}
이 모듈의 함수들은 Time 구조체뿐 아니라 Time 구조체와 같은 필드를 가진 어떤 구조체(NaiveDateTime, DateTime 등)에도 동작해요. 이런 함수들은 타입스펙에서 t/0 대신 Calendar.time/0을 요구해요. 개발자는 Time 구조체를 직접 만들기보다 이 모듈이 제공하는 함수나 서드파티 달력 라이브러리의 함수에 의존하는 게 좋아요.
출처: Time
본문
시각 비교
==/2, >/2, </2 같은 연산을 통한 비교는 구조적(structural) 비교예요. 즉 Time 구조체의 필드를 기준으로 비교해요. 시각끼리 제대로 비교하려면 compare/2, after?/2, before?/2 함수를 쓰세요. 이 모듈에 compare/2가 있기 때문에 Enum.min/2, Enum.max/2로 Enum에서 최소·최대 시각을 구할 수도 있어요.
iex> Enum.min([~T[23:00:07.001], ~T[10:00:07.001]], Time)
~T[10:00:07.001]
주요 함수 살펴보기
Time.add/3는 주어진 시각에 단위 수만큼을 더해요. :hour, :minute, :second 또는 System.time_unit/0의 아무 서브초 정밀도 단위를 받지만, 결국 모두 마이크로초로 변환돼요. 음수 값은 시간을 거꾸로 움직이고, 기본 정밀도는 :second예요. 결과 값은 하루 중의 시각을 나타내므로 순환적(cyclic)이에요. 예를 들어 ISO 달력에서는 24시간을 넘지 않아요.
iex> Time.add(~T[10:00:00], 27000)
~T[17:30:00]
iex> Time.add(~T[11:00:00.005], 2400)
~T[11:40:00.005]
iex> Time.add(~T[23:00:00], -60)
~T[22:59:00]
iex> Time.add(~T[17:10:05], 86400)
~T[17:10:05]
add/3보다는 더 편리한 API인 shift/2를 권장해요. add/3는 항상 Calendar.ISO 기준으로 단위를 계산해요.
compare/2는 두 시각을 비교해 첫 시각이 더 늦으면 :gt, 더 이르면 :lt, 같으면 :eq를 반환해요. 날짜 필드만 고려하므로 더 복잡한 달력 타입끼리도 시각만 비교할 수 있어요.
iex> Time.compare(~T[16:04:16], ~T[16:04:28])
:lt
iex> Time.compare(~T[16:04:16], ~T[16:04:16])
:eq
iex> Time.compare(~N[1900-01-01 16:04:16], ~N[2015-01-01 16:04:16])
:eq
new/4는 모든 값을 정수로 받아요. 각 값이 적절한 범위에 들어가면 {:ok, time}을, 아니면 {:error, reason}을 반환해요. 마이크로초는 0~6 사이의 정수인 정밀도와 함께 줄 수도 있어요. 내장 달력은 윤초(leap second)를 지원하지 않아요.
iex> Time.new(0, 0, 0, 0)
{:ok, ~T[00:00:00.000000]}
iex> Time.new(23, 59, 59, 999_999)
{:ok, ~T[23:59:59.999999]}
iex> Time.new(24, 59, 59, 999_999)
{:error, :invalid_time}
diff/3는 두 시각의 차이를 반환하는데, 시간·분·초·마이크로초만 고려해요. NaiveDateTime나 DateTime를 넘기면 시각 부분만 보며, 날짜나 시간대 정보는 차이 계산에서 무시돼요. 결과는 :hour, :minute, :second 또는 System.time_unit/0의 서브초 단위 중 아무 단위로 받을 수 있어요. 첫 시각이 더 이르면 음수가 나와요. 소수 결과는 지원하지 않고 잘려나가요(truncated).
iex> Time.diff(~T[00:29:12], ~T[00:29:10])
2
iex> Time.diff(~T[00:29:12], ~T[00:29:10], :microsecond)
2_000_000
iex> Time.diff(~T[02:29:10], ~T[00:29:10], :hour)
2
from_iso8601/2는 ISO 8601:2019에 설명된 확장 "Local time" 포맷을 파싱해요. 문자열에 시간대 오프셋이 포함될 수 있지만, 시각에는 그런 정보가 없으므로 그냥 버려져요. 표준에 따라 이 함수 안에서는 모호함이 없으므로 구분자 "T"는 원하면 생략할 수 있어요.
to_iso8601/2는 시각을 ISO 8601:2019로 변환해요. 기본적으로 사람이 읽기 좋은 "extended" 포맷을 반환하며, :basic 옵션을 넘기면 "basic" 포맷도 지원해요.
to_erl/1은 시각을 Erlang 시간 튜플로 변환해요. Erlang 시간 튜플은 시·분·초만 담으므로 정밀도 손실이 발생할 수 있다는 점을 주의하세요.
truncate/2는 마이크로초 필드를 주어진 정밀도(:microsecond, :millisecond, :second)로 잘라요. 이미 주어진 정밀도보다 낮은 정밀도를 갖고 있으면 그대로 돌려줘요.
utc_now/1은 현재 UTC 시각을 반환해요. 시간 단위를 넘기면 결과를 자동으로 잘라주고, 아무것도 안 넘기면 기본값 :native로 마이크로초 해상도를 얻어요.
더 알아보기
Calendar모듈 문서에서 달력·시간대 관련 개념을 자세히 볼 수 있어요.- 시각에 날짜가 함께 필요하다면
Date,DateTime,NaiveDateTime문서를 참고하세요. Duration모듈과Time.shift/2를 함께 보면 기간(지속 시간) 처리 흐름을 이해하는 데 도움이 돼요.