NaiveDateTime — 시간대가 없는 날짜·시간

NaiveDateTime — 시간대가 없는 날짜·시간

NaiveDateTime시간대(time zone) 없이 날짜와 시간을 담는 구조체(struct) 예요. 이름의 "naive"(순진한)라는 말이 이 구조의 성격을 그대로 드러내요. 시간대 개념이 빠져 있다 보니 실제로 존재하지 않을 수도 있는 시각까지 그냥 표현해 버리죠.

출처: NaiveDateTime

본문

NaiveDateTime 구조체는 year, month, day, hour, minute, second, microsecond, calendar 필드를 가져요. 새 naive datetime은 new/2, new/8 함수나 ~N 시길(sigil_N/2)로 만들 수 있어요:

iex> ~N[2000-01-01 23:00:07]
~N[2000-01-01 23:00:07]

구조체 안의 날짜·시간 필드는 직접 접근할 수 있어요:

iex> naive = ~N[2000-01-01 23:00:07]
iex> naive.year
2000
iex> naive.second
7

왜 "naive"라고 부르는 걸까요. 이 datetime 표현에는 시간대가 없어서, 어떤 지역에서는 전혀 존재하지 않는 시각이라도 형식상으로는 유효한 값으로 남아 있어요. 예를 들어 어떤 지역이 서머타임(daylight saving)을 적용하면 시계는 보통 한 시간 앞으로 또는 뒤로 움직여요. 그 결과 어떤 시각은 아예 발생하지 않거나, 반대로 두 번 이상 발생하기도 해요. NaiveDateTime은 시간대 기준으로 검증되지 않으니까 이런 오류가 그대로 눈에 띄지 않고 지나갈 수 있어요.

그래서 개발자는 NaiveDateTime 구조체를 직접 만들기보다는, 이 모듈이 제공하는 함수나 서드파티 달력 라이브러리의 함수를 사용하는 게 안전해요.

naive datetime 비교하기

Elixir에서 ==/2, >/2, </2 같은 비교는 구조적(structural)이에요. 즉 NaiveDateTime 구조체의 필드 값을 기준으로 비교해요. naive datetime끼리 제대로 된 비교를 하려면 compare/2, after?/2, before?/2 함수를 쓰세요. 이 모듈에 compare/2가 있다는 것 덕분에 Enum.min/2, Enum.max/2로 Enum 안에서 최소·최대 naive datetime을 구할 수도 있어요:

iex> Enum.min([~N[2020-01-01 23:00:07], ~N[2000-01-01 23:00:07]], NaiveDateTime)
~N[2000-01-01 23:00:07]

에포크(epoch) 다루기

add/3diff/3는 시각을 계산하거나, 두 순간 사이의 초 수를 구할 때 써요. 예를 들어 Unix 에포크(1970-01-01 00:00:00)로부터 몇 초가 지났는지 계산해 볼게요:

iex> NaiveDateTime.diff(~N[2010-04-17 14:00:00], ~N[1970-01-01 00:00:00])
1271512800

iex> NaiveDateTime.add(~N[1970-01-01 00:00:00], 1_271_512_800)
~N[2010-04-17 14:00:00]

이 함수들은 위의 Unix 에포크나 그레고리오 에포크(0000-01-01 00:00:00) 같은 흔한 에포크를 처리할 때 최적화되어 있어요.

더 알아보기

  • DateTime — 시간대 정보를 갖는 날짜·시간 구조체
  • Time, Date — 각각 시간과 날짜만 다루는 구조체
  • NaiveDateTime.diff/3, NaiveDateTime.add/3 — 초 단위 계산
  • ~N 시길과 new/2, new/8 — naive datetime 생성