프로젝트를 진행하면서 timezone 모듈과 datetime 모듈을 사용하였는데, 두 개다 시간을 다루는 모듈이라고만 인지하고 있었고 무슨 차이가 있는지 어떤 장단점이 있고 어떤 상황에 사용해야 하는지 잘 이해를 하지 못한 채로 사용하고 있었는데, 아무래도 정리가 필요한 것 같아서 찾아보니 생각보다 큰 차이점이 있었다.
간단히 이야기하자면, datetime은 날짜와 시간 정보를 다루는 데 사용되고,datetime에 추가적으로 timezone은 시간대 정보를 관리하는 데 사용된다.
시간을 처리할 때 시간대는 왜 중요할까?
다른 프로젝트를 할 때는 잘 느끼지 못하였는데 시간대를 맞추는것은 매우 중요한 역할을 한다. 나라 또는 지역마다 살아가는 시간이 다르기 때문에 편차가 존재하는데, 이러한 시간대의 차이는 업무 스케줄 관리, 국제 협업, 법적문제, 금융 관련 사항에서는 매우 중요하다.
예를 들어보면, 우리나라와 미국 간의 금융거래가 있는데, 두 나라 모두 시간이 다르다는 걸 인지하지 못했다고 생각해 보자. 우라 나라와 미국 사이에는 13시간의 시차가 있기 때문에 송금 확인증을 받은 사람이 이를 올바르게 해석하지 못할 수 있습니다.
우라 나라의 시간은 미국(워싱턴 DC)보다 13시간이 빠른데, 우리나라에서 날짜 정보 없이 오후 1시 30분에 송금을 했다라고 확인증을 보냈다. 하지만 미국은 아직 오전 12시 30분이고 이럼 미국에선 13시간 후인 1시 30분에 송금을 하겠다는 건지 13시간 전에 송금을 했다는 건지 헷갈릴 수 또 있다. 사실 미국의 오전 12시 30분이 한국의 오후 1시 30분과 같기 때문에 실시간으로 전송된 상황인데 말이다.
이를 예방하기 위해서 시간대를 명시하거나 표준 시간을 사용함으로써 이러한 혼란을 줄일 수 있다.
앞선 예시에 대해서 마저 이야기해보자면 한국사람이 돈을 보내고 "한국 시간 기준 오후 1시 30분에 송금"이라고 보낸다거나, 표준시간을 지정해서 그 시간을 기준으로 이야기하는 방법이 있다.
timezone과 datetime 차이점
차이점을 제대로 몰라서 혼용하여 사용했던 경험이 있고, 그런 사람들이 많을 것이라고 생각하는데, 시간대의 포함 여부가 차이점이 가장 큰 차이점이 아닐까 싶다. 어떻게 보면 datetime+시간대(django.settings) = timezone이 되는것 같다.
timezon: Django에서 시간대 관련 작업을 위한 특별한 모듈로, 시간대 변환, 시간대 관련 설정등을 처리한다.
datetime: Python의 표준라이브러리이기 때문에 모든 Python 프로젝트에서 사용 가능하다. 기본적으로 로컬 시간대로 설정
datetime 모듈 자체는 시간대에 대한 정보를 포함하지 않습니다. 기본적으로 로컬 시간을 나타내는데, 이는 컴퓨터의 시스템 설정에 따라 달라질 수 있다.
하지만 datetime 모듈을 사용하여 객체를 생성하거나 시간 연산을 수행할 때 시간대 정보를 함께 처리할 수 있다. 예를 들어, datetime.datetime 클래스의 객체를 생성할 때 tzinfo 매개변수를 사용하여 시간대 정보를 추가할 수 있지만 이러한 방식은 일반적으로 권장되지 않는다.
datetime 모듈의 시간대 처리 기능은 제한적이며, 오류가 발생하기 쉽기 때문에 Python에서는 pytz 라이브러리와 같은 외부 라이브러리를 사용하여 시간대를 처리하는 것이 일반적이고, Django에서는 timezone 모듈을 통해 시간대 처리를 보다 편리하게 할 수 있다.
datetime 사용하기
datetime
날짜와 시간 정보를 포함하는 객체를 나타낸다.
from datetime import datetime, timezone, timedelta
# datetime.now([tz]) - 현재 시간을 로컬 시간대로 반환
now = datetime.now()
print(now) # 현재 로컬 시간 (예: 2024-06-04 12:34:56.789123)
# 시간대(tz)를 지정하여 현재 시간을 UTC로 반환
now_utc = datetime.now(timezone.utc)
print(now_utc) # 현재 UTC 시간 (예: 2024-06-04 09:34:56.789123+00:00)
# datetime.utcnow() - UTC 기준의 현재 시간을 반환
utc_now = datetime.utcnow()
print(utc_now) # 현재 UTC 시간 (예: 2024-06-04 09:34:56.789123)
# datetime.strptime(date_string, format) - 문자열 형식의 날짜 및 시간 정보를 datetime 객체로 변환
date_str = '2024-06-04 12:34:56'
dt = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')
print(dt) # 2024-06-04 12:34:56
# datetime.strftime(format) - datetime 객체를 문자열로 변환
formatted_str = dt.strftime('%A, %B %d, %Y %H:%M:%S')
print(formatted_str) # 'Tuesday, June 04, 2024 12:34:56'
# datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]) - 특정 필드를 교체한 새로운 datetime 객체를 반환
new_dt = dt.replace(year=2025)
print(new_dt) # 2025-06-04 12:34:56
# 주요 속성
print(dt.year) # 2024
print(dt.month) # 6
print(dt.day) # 4
print(dt.hour) # 12
print(dt.minute) # 34
print(dt.second) # 56
print(dt.microsecond) # 0
date
날짜 정보를 나타내는 객체를 생성한다. (시간 정보는 없음)
from datetime import date
# date - 특정 연도, 월, 일을 객체로 생성
d = date(2024, 6, 4)
print(d) # 2024-06-04
# today - 현재 날짜를 반환
today = date.today()
print(today) # 현재 날짜 (예: 2024-06-04)
# fromisoformat (문자열 -> 객체)
d = date.fromisoformat('2024-06-04')
print(d) # 2024-06-04
# isoformat (객체 -> 문자열)
d = date(2024, 6, 4)
iso_str = d.isoformat()
print(iso_str) # '2024-06-04'
# replace - 특정 필드를 교체후 객체로 반환
d = date(2024, 6, 4)
new_date = d.replace(year=2025)
print(new_date) # 2025-06-04
# 주요 속성
d = date(2024, 6, 4)
print(d.year) # 2024
print(d.month) # 6
print(d.day) # 4
# weekday - 요일을 정수로 반환
d = date(2024, 6, 4)
print(d.weekday()) # 1 (화요일)
# ctime - C스타일 문자열로 변환
d = date(2024, 6, 4)
print(d.ctime()) # 'Tue Jun 4 00:00:00 2024'
# strftime - 객체를 지정된 형식의 문자열로 변환
d = date(2024, 6, 4)
print(d.ctime()) # 'Tue Jun 4 00:00:00 2024'
time
시간 정보를 나타내는 객체를 생성한다. (날짜 정보는 없음)
from datetime import time
# time - 특정 시간 정보를 포함하는 객체를 생성
t = time(14, 30, 45, 500000)
print(t) # 14:30:45.500000
# 주요 속성
print(t.hour) # 14
print(t.minute) # 30
print(t.second) # 45
print(t.microsecond) # 500000
# replace - 특정 필드를 교체한 새로운 time 객체를 반환
new_time = t.replace(hour=16)
print(new_time) # 16:30:45.500000
# isoformat - time 객체를 ISO 8601 형식의 문자열로 변환
iso_str = t.isoformat()
print(iso_str) # '14:30:45.500000'
# strftime - time 객체를 지정된 형식의 문자열로 변환
formatted_time = t.strftime('%H:%M:%S.%f')
print(formatted_time) # '14:30:45.500000'
timedelta
두 날짜 또는 시간 간의 차이를 나타낸다.
from datetime import datetime, timedelta
# timedelta - 특정 기간을 나타내는 객체를 생성
delta = timedelta(days=5, hours=3, minutes=15)
print(delta) # 5 days, 3:15:00
# 현재 날짜와 시간
now = datetime.now()
print(now) # 현재 날짜와 시간 (예: 2024-06-04 12:34:56.789123)
# 날짜와 시간에 timedelta 더하기
future = now + delta
print(future) # 현재 시간으로부터 5일 3시간 15분 후의 날짜와 시간
# 날짜와 시간에서 timedelta 빼기
past = now - delta
print(past) # 현재 시간으로부터 5일 3시간 15분 전의 날짜와 시간
# timedelta의 속성
print(delta.days) # 5
print(delta.seconds) # 11700 (3시간 15분을 초로 환산)
print(delta.microseconds) # 0
# total_seconds - timedelta 객체의 전체 기간을 초 단위로 반환
print(delta.total_seconds()) # 439500.0 (5일 3시간 15분을 초로 환산)
tzinfo
시간대 정보를 나타내는 기본 클래스, 사용자 정의 시간대 클래스를 만들 때 사용된다.
from datetime import tzinfo, timedelta, datetime
class MyTimezone(tzinfo):
def __init__(self, offset_hours, name):
self.offset = timedelta(hours=offset_hours)
self.name = name
def utcoffset(self, dt):
return self.offset
def dst(self, dt):
return timedelta(0)
def tzname(self, dt):
return self.name
# 사용자 정의 시간대 객체 생성
my_tz = MyTimezone(-5, 'MyTZ')
# 현재 시간
now = datetime.now()
print(now) # 현재 로컬 시간 (예: 2024-06-04 12:34:56.789123)
# 현재 시간을 사용자 정의 시간대로 변환
now_with_tz = now.replace(tzinfo=my_tz)
print(now_with_tz) # 현재 시간에 사용자 정의 시간대 적용 (예: 2024-06-04 12:34:56.789123-05:00)
# 사용자 정의 시간대의 UTC 오프셋
print(now_with_tz.utcoffset()) # -1 day, 19:00:00 (UTC-5 시간대)
print(now_with_tz.tzname()) # 'MyTZ'
참고
'BackEnd > Django, DRF' 카테고리의 다른 글
[Custom] path와 re_path, CustomConverter를 통한 url 정의하기 (0) | 2024.06.10 |
---|---|
[Django] 동적 이미지 생성, CSV & 엑셀 응답을 처리하는 View 만들기 (0) | 2024.06.10 |
[DRF] Django로 일간 및 주간 조회수 구현하기: 코드 예제 (0) | 2024.06.04 |
[JWT] Custom JWT 관련 middleware와 backend (0) | 2024.05.31 |
[회고록] 효율적인 Django 시작하기: initialize_django 프로젝트 (0) | 2024.05.27 |