pandas 시간 dtype 총정리 datetime64ns datetime64ns tz timedelta64ns Period
⏱️ 시간 데이터 분석의 핵심을 한 번에 정리해 정확한 처리와 빠른 연산을 돕습니다
데이터를 다루다 보면 날짜와 시간이 포함된 열이 분석 전체의 정확도를 좌우하곤 합니다.
보고서 마감이 코앞인데 타임존이 섞여 있거나 결측이 숨어 있으면 필터도 틀어지고 집계도 어긋나죠.
이럴 때 가장 확실한 해결책은 데이터를 올바른 시간 dtype으로 정리하는 일입니다.
pandas는 시각 데이터용으로 여러 dtype을 제공하지만 이름이 비슷해 보이고 동작 차이도 미묘해서 처음에는 막막할 수 있습니다.
한 번 기준을 잡아두면 파싱, 정렬, 리샘플링, 시차 보정 같은 반복 작업이 훨씬 깔끔해지고, 이후 파이프라인에서도 재활용이 쉬워집니다.
이 글은 pandas의 시간 관련 dtype을 실제 분석 흐름에 맞춰 설명합니다.
특히 datetime64ns, 타임존 정보를 담는 datetime64ns tz, 경과 시간을 표현하는 timedelta64ns, 그리고 회계기간·주기 분석에 쓰이는 Period까지 핵심 개념을 빠짐없이 다룹니다.
또한 널 모델과 결측 처리 전략을 함께 정리해 일관된 기준으로 누락값을 다루는 방법을 제시합니다.
복잡한 옵션을 암기하기보다 “언제 어떤 dtype을 선택해야 하는가”에 초점을 맞춰 실무 적용이 쉬운 예시와 체크포인트로 안내하겠습니다.
📋 목차
🔗 유형별 정의와 특징
pandas가 시간 데이터를 표현하는 핵심 dtype은 네 가지로 정리됩니다.
먼저 datetime64[ns]는 타임존 정보가 없는 시점(naive timestamp)을 나노초 정밀도로 저장합니다.
파일·API에서 읽은 문자열을 pd.to_datetime으로 변환하면 가장 흔히 이 타입이 됩니다.
다음으로 datetime64[ns, tz]는 명시적인 타임존을 포함하는 시점(aware timestamp)으로, 지역 시각 혼동을 막고 교차 지역 로그 정렬·리샘플링에 안전합니다.
세 번째 timedelta64[ns]는 두 시점 간 간격이나 지속시간을 나타내며, 평균 처리 시간·세션 길이 같은 지표 계산에 적합합니다.
마지막으로 Period는 ‘하루·월·분기’처럼 구간 자체를 표현하며, 회계연도 분석이나 캘린더 그룹핑을 깔끔하게 처리합니다.
널 모델은 시간 계열의 신뢰도를 좌우합니다.
datetime·timedelta·period 계열의 결측치는 공통적으로 NaT(Not-a-Time)로 표현됩니다.
즉, datetime64[ns]와 datetime64[ns, tz], timedelta64[ns], Period 모두 결측을 NaT로 통일해 연산 시 자동 전파가 이뤄지며, isna(), fillna()와 같은 결측 처리 API와 호환됩니다.
수치형에서 쓰는 pd.NA와 구분된다는 점이 포인트입니다.
또한 dtype 간의 변환에서는 의미가 보존되어야 하므로, 시점↔기간 변환 시 빈도(freq)를 명확히 지정해 애매한 해석을 예방하는 것이 좋습니다.
| dtype | 핵심 포인트 |
|---|---|
| datetime64[ns] | 타임존 없는 시점. 정렬·리샘플 기본형. 입력 파싱 시 기본 값. 결측은 NaT. |
| datetime64[ns, tz] | 타임존 포함 시점. 타 지역 로그/거래 데이터 병합에 안전. UTC 기준 저장·변환 권장. 결측은 NaT. |
| timedelta64[ns] | 지속시간·간격. 평균/합계/분위수 등 집계 용이. 음수 가능. 결측은 NaT. |
| Period | 연·분기·월·주 등 구간 자체. 정확한 캘린더 그룹핑·회계분석. freq 필수.결측은 NaT. |
import pandas as pd
ts = pd.to_datetime(["2025-10-01 12:00", None]) # datetime64[ns] + NaT
tsz = ts.dt.tz_localize("Asia/Seoul").dt.tz_convert("UTC") # datetime64[ns, tz]
dt = pd.to_timedelta([30, None], unit="m") # timedelta64[ns] + NaT
per = pd.PeriodIndex(["2025-10", None], freq="M") # Period[M] + NaT
# 널 모델 확인
print(ts.dtype, ts.isna().sum())
print(tsz.dtype, tsz.isna().sum())
print(dt.dtype, dt.isna().sum())
print(per.dtype, per.isna().sum())
💡 TIP: 로깅·거래 데이터처럼 지역이 섞인 경우에는 입력 즉시 UTC로 통일하고, 사용자 표시 단계에서만 로컬 타임존으로 변환하면 서머타임 이슈와 교차 지역 연산 오류를 최소화할 수 있습니다.
⚠️ 주의: Period로 그룹핑할 때 freq를 지정하지 않으면 월말 기준인지 주간 기준인지가 모호해질 수 있습니다.
또한 문자열 월(YYYY-MM)을 시점으로 착각해 datetime64[ns]로 변환하면 말일 길이에 따라 집계가 틀어질 수 있습니다.
🛠️ datetime64ns와 datetime64ns tz
pandas에서 가장 기본적인 시간 dtype은 datetime64[ns]입니다.
이 타입은 타임존 정보가 없는 단순 시점을 나노초 단위 정밀도로 저장합니다.
CSV, Excel, SQL 등에서 날짜 문자열을 읽어올 때 기본 변환되는 타입이며, 시계열 정렬·슬라이싱·리샘플링 같은 연산이 가능합니다.
하지만 여러 지역의 데이터를 통합할 때는 시간대가 뒤섞여 혼란이 생길 수 있습니다.
이를 해결하는 dtype이 datetime64[ns, tz]입니다.
여기서는 타임존을 명시하여 ‘의미 있는 시각’을 다룹니다.
예를 들어 서울·뉴욕 서버 로그를 동시에 분석할 때, 각 데이터에 해당 지역 타임존을 부여하면 올바르게 정렬됩니다.
내부적으로는 UTC를 기준으로 저장되며, 필요할 때만 로컬 시간대로 변환해 표시합니다.
따라서 글로벌 서비스나 다지역 트래픽 분석에서는 이 타입을 사용하는 것이 안정적입니다.
🌍 타임존 변환의 기본
타임존 처리는 두 단계로 나눌 수 있습니다.
먼저 tz_localize로 현재 값이 어느 지역 시각인지 지정합니다.
그 후 tz_convert로 원하는 지역 시간대로 변환합니다.
만약 로컬 타임존 없이 변환만 시도하면 오류가 발생합니다.
import pandas as pd
dt = pd.to_datetime(["2025-10-01 09:00", "2025-10-01 21:00"])
print(dt.dtype) # datetime64[ns]
# 서울 시간대로 지정
dt_seoul = dt.tz_localize("Asia/Seoul")
print(dt_seoul.dtype) # datetime64[ns, Asia/Seoul]
# 뉴욕 시간대로 변환
dt_ny = dt_seoul.tz_convert("America/New_York")
print(dt_ny)
📅 실제 활용 예시
온라인 쇼핑몰의 주문 로그를 분석할 때, 고객은 현지 시간을 기준으로 이벤트를 기억합니다.
하지만 서버는 UTC를 기록하기 때문에, 마케팅 분석이나 고객 서비스 대응에는 datetime64[ns, tz]가 필수적입니다.
예를 들어 “밤 12시에 결제했다”고 고객이 말했을 때, 정확히 어느 나라의 자정인지 구분할 수 있어야 문제 해결이 가능합니다.
- 🛠️datetime64[ns]는 타임존 없는 기본 시점
- 🌍datetime64[ns, tz]는 UTC 기준 저장, 표시만 로컬 변환
- ⚡데이터 통합 시 UTC로 표준화 후 분석 권장
⚙️ timedelta64ns의 연산과 활용
시간 간격이나 지속 시간을 표현할 때는 timedelta64[ns] dtype을 사용합니다.
이는 두 시점 간의 차이를 저장하며, 나노초 단위 정밀도를 지원합니다.
로그 분석에서 요청-응답 시간, 사용자의 체류 시간, 이벤트 간격을 계산할 때 유용합니다.
또한 음수 값도 허용되므로 ‘예상보다 늦음’ 같은 시간 지연 분석도 가능합니다.
pandas는 timedelta64[ns]에 대해 다양한 수학적 연산과 집계를 지원합니다.
평균, 합계, 최솟값·최댓값은 물론, 특정 시간 단위(초, 분, 일)로 변환하여 비교할 수도 있습니다.
이는 단순한 계산을 넘어 SLA(서비스 수준 협약) 준수 여부를 모니터링하거나, 고객 여정에서 병목 구간을 발견하는 데 큰 도움이 됩니다.
⏳ timedelta 계산 예시
import pandas as pd
# 두 시점 간 차이 계산
start = pd.to_datetime(["2025-10-01 08:00", "2025-10-01 09:30"])
end = pd.to_datetime(["2025-10-01 09:15", "2025-10-01 10:00"])
delta = end - start
print(delta)
# dtype: timedelta64[ns]
# 평균 체류 시간 계산
print(delta.mean())
# 분 단위로 변환
print(delta / pd.Timedelta(minutes=1))
위 예시에서 timedelta 연산은 자동으로 NaT를 처리하며, 결측이 있는 경우에도 평균이나 합계를 계산할 수 있습니다.
또한 timedelta는 다른 시점과 결합해 새로운 시점을 생성할 수도 있습니다.
예를 들어 “시작일 + 7일”과 같이 기간을 더해 마감일을 예측하는 방식입니다.
📊 활용 시나리오
- 📌사용자 세션 길이 분석 (입장 시각 ~ 퇴장 시각)
- 📌서비스 응답 속도 모니터링 (요청 ~ 응답까지의 지연)
- 📌프로젝트 일정 관리 (계획 대비 실제 소요 시간 비교)
⚠️ 주의: timedelta를 문자열로 변환할 때는 일(day), 시간(hour), 분(minute) 단위가 자동 변환되므로, 단위별 집계가 필요하다면 반드시 pd.Timedelta를 사용해 명시적으로 변환해야 합니다.
🔎 Period와 기간 연산
시계열 분석에서 특정 구간 자체를 다뤄야 할 때는 Period dtype이 적합합니다.
datetime이 ‘하나의 시점’을 표현한다면, Period는 ‘월, 분기, 연도, 주기 같은 기간’을 표현합니다.
예를 들어 “2025년 3분기”라는 데이터는 특정 날짜가 아닌 2025-07-01부터 2025-09-30까지의 구간을 의미하며, 이는 회계 보고나 매출 분석에서 매우 자주 쓰입니다.
Period는 반드시 freq(빈도)를 가져야 합니다.
freq에는 “A”(연도), “Q”(분기), “M”(월), “W”(주), “D”(일) 등이 있으며, 지정된 단위에 따라 구간이 정해집니다.
datetime에서 Period로 변환하면 기준이 되는 freq에 맞춰 기간이 결정되며, 반대로 Period에서 datetime으로 변환하면 해당 구간의 시작일이나 종료일을 기준으로 변환할 수 있습니다.
📈 Period 활용 예시
import pandas as pd
# 월 단위 Period
p = pd.Period("2025-03", freq="M")
print(p) # 2025-03
print(p.start_time, p.end_time)
# 분기 단위 PeriodIndex
pq = pd.period_range("2025Q1", periods=4, freq="Q")
print(pq)
# datetime -> Period 변환
dt = pd.to_datetime(["2025-03-15", "2025-07-20"])
per = dt.to_period("Q")
print(per)
# Period -> datetime 변환 (시작일 기준)
print(per.to_timestamp())
위 예시는 월 단위 Period를 생성하고, 분기별 인덱스를 만드는 방법을 보여줍니다.
특히 to_period와 to_timestamp는 Period와 datetime 간 변환에서 가장 많이 사용되는 함수입니다.
💡 실무에서의 Period 활용
- 📊회계 연도별 실적 집계
- 📊월간/분기별 매출 분석
- 📊캘린더 기반 리샘플링 (주간, 분기 기준)
💬 Period는 ‘시점’보다 ‘기간’을 다루기에 적합합니다.
특히 시계열 집계에서 경계값이 애매해지는 문제를 예방하는 데 강력한 도구가 됩니다.
💡 널 모델과 결측 처리 전략
시간 데이터를 다루는 과정에서 결측값은 흔히 등장합니다.
pandas는 시간 관련 dtype에서 결측을 NaT(Not-a-Time)으로 통일해 처리합니다.
이는 datetime64[ns], datetime64[ns, tz], timedelta64[ns], Period 모두 동일합니다.
즉, 시점·기간·차이 계산 중 결측이 있으면 NaT가 그대로 전파되며, 연산 결과도 일관되게 NaT로 처리됩니다.
이러한 특성 덕분에 결측 처리를 위한 pandas의 기본 함수 isna(), fillna(), dropna()가 시간 dtype에도 똑같이 적용됩니다.
따라서 널 모델을 이해하면 결측 데이터를 안전하게 관리할 수 있고, 리샘플링이나 집계 과정에서도 예기치 못한 오류를 줄일 수 있습니다.
🧩 결측 처리 기본 전략
- 🔍isna()로 NaT 위치 확인
- 🧹fillna()로 보간값·고정값·앞뒤 시점으로 대체
- ✂️dropna()로 불필요한 NaT 제거
import pandas as pd
ts = pd.to_datetime(["2025-10-01", None, "2025-10-03"])
print(ts)
# [2025-10-01, NaT, 2025-10-03]
# NaT 확인
print(ts.isna())
# 보간값으로 채우기
filled = ts.fillna(method="ffill")
print(filled)
# NaT 제거
clean = ts.dropna()
print(clean)
⚡ 결측 처리 시 유용한 팁
💡 TIP: 시계열 분석에서는 단순히 NaT를 삭제하기보다는, 앞뒤 시점으로 보간하거나 평균값을 채워 넣는 방식이 더 안정적인 경우가 많습니다.
특히 주기성이 있는 데이터(예: 일별 매출)에서는 interpolate() 함수를 활용하면 자연스러운 결측 보정이 가능합니다.
⚠️ 주의: NaT는 datetime 계열의 널 값이므로, pd.NA와 혼동하면 안 됩니다.
NaT는 시간 연산에서 안전하게 전파되지만, pd.NA는 불리언 연산 시 에러를 유발할 수 있습니다.
❓ 자주 묻는 질문 (FAQ)
datetime64[ns]와 datetime64[ns, tz]의 차이는 무엇인가요?
NaT와 NaN의 차이는 뭔가요?
timedelta64[ns]에서 음수 값도 표현할 수 있나요?
Period와 datetime은 언제 구분해서 써야 하나요?
NaT가 있는 경우 평균이나 합계 계산은 어떻게 되나요?
to_period()와 to_timestamp()는 어떤 차이가 있나요?
timedelta를 초 단위로 변환하려면 어떻게 하나요?
타임존 데이터는 항상 UTC로 변환해야 하나요?
📌 시간 dtype을 이해하면 시계열 분석이 쉬워진다
pandas에서 제공하는 시간 dtype은 크게 네 가지로 구분됩니다.
시점을 나타내는 datetime64[ns], 타임존이 포함된 datetime64[ns, tz], 두 시점 간 차이를 다루는 timedelta64[ns], 그리고 기간 자체를 표현하는 Period입니다.
이 네 가지는 모두 NaT라는 통일된 널 모델을 사용해 결측 처리가 일관적이며, to_period(), to_timestamp(), tz_localize(), tz_convert() 같은 변환 메서드로 유연하게 연결할 수 있습니다.
데이터 전처리 단계에서 올바른 시간 dtype을 선택하는 것은 단순한 형식 문제가 아니라 분석 전체의 정확도와 직결됩니다.
예를 들어 글로벌 로그 데이터를 UTC 기준으로 저장한 뒤 로컬 타임존으로 변환하면 서머타임 이슈를 예방할 수 있고, 월·분기 단위의 매출 분석에서는 Period를 활용해 경계값 혼동을 방지할 수 있습니다.
또한 timedelta를 통해 체류 시간이나 응답 속도를 계산하면 서비스 품질 개선에도 직접적인 인사이트를 얻을 수 있습니다.
즉, pandas의 시간 dtype을 정확히 이해하고 적용하는 것은 데이터 사이언스 실무에서 필수적인 기본기입니다.
결측 처리, 변환, 연산이 모두 안정적으로 지원되기 때문에 다양한 분석 환경에서 일관성을 유지할 수 있으며, 복잡한 시계열 데이터도 보다 직관적으로 다룰 수 있습니다.
🏷️ 관련 태그 : pandas, datetime64, timedelta64, Period, NaT, 데이터분석, 시계열데이터, 파이썬데이터처리, 타임존, 결측치처리