Django를 처음 설치하면, 시간과 관련된 설정이 아래와 같이 되어 있습니다.
# settings.py
TIME_ZONE = 'UTC'
우선, UTC가 무엇일까요?
UTC (협정 세계시)는 Coordinated Universal Time의 약자로, 세계 표준 시간을 의미합니다. UTC는 현대 국제 시간 체계의 기준으로 사용되며, 지구의 자전 속도와 태양 시간을 기반으로 합니다. UTC는 전 세계의 시간대와 동기화되어 있어, 국제적인 커뮤니케이션과 데이터 처리에 있어서 일관된 시간을 제공합니다.
UTC는 그리니치 평균시 (GMT)와 동일한 시간대를 기준으로 하지만, 두 개념 사이에는 약간의 차이가 있습니다. GMT는 지구 자전 속도를 기준으로 한 시간 체계이지만, UTC는 원자시계를 기준으로 정확한 시간을 유지하므로, 초 단위에서의 정확도가 더 높습니다.
세계의 시간대는 UTC를 기준으로 앞뒤로 시간이 차이납니다. 예를 들어, 한국 시간대는 UTC+9로, UTC보다 9시간 빠른 시간을 사용합니다. 미국 동부 표준시는 UTC-5로, UTC보다 5시간 느린 시간을 사용합니다.
컴퓨터 시스템에서는 일반적으로 UTC를 기준으로 시간을 저장하고 처리하며, 필요에 따라 사용자에게 표시될 때 로컬 시간대로 변환됩니다. 이렇게 함으로써 전 세계에서 일관된 시간 처리를 보장할 수 있습니다.
Django의 기본 시간 기준 - UTC
Django는 시간을 기본적으로 UTC 기준으로 다룹니다.
시간을 다룬다는 것은 크게 아래의 두가지 경우라 볼 수 있습니다.
1) 시간이 저장될 떄
2) 시간이 조회될 때
Django는 일관된 시간 처리를 보장하기 위해, 데이터베이스에 시간 저장을 UTC 기준으로 합니다.
그렇다면 설정을 아래와 같이 한국 기준으로 했을 때 한국 시간에 맞게 저장이 될까요?
# settings.py
TIME_ZONE = 'Asia/Seoul'
그렇지 않습니다.
TIME_ZONE 설정 값을 변경하면, 템플릿이나 DB에 저장된 시간을 불러왔을 때
'Asia/Seoul' 이라는 로컬 시간에 맞춰서 변형되어 출력이 되지만,
시간을 저장하는 것은 여전히 UTC 기준을 따르게 되어 있습니다.
위와 같은 이유 때문에 TIME_ZONE을 UTC에서 다른 값으로 변경한 후에
시간을 가지고 더하고 빼는 등의 계산을 한 값을 DB에 넣고 출력해보면,
뭔가 생각했던 값이 그대로 출력이 되지 않는 경우를 마주하게 됩니다.
현재 시간과, 현재로부터 3일 뒤의 23시 59분 59초를 구해보는 예를 살펴봅시다.
# settings.py
TIME_ZONE = 'Asia/Seoul'
USE_TZ = True
# views.py
from dango.utils import timezone
from dateutil.relativedelta import relativedelta
print(timezone.now())
print((timezone.now() + relativedelta(days=3)).replace(hour=23, minute=59, second=59))
# output
# 2023-04-10 13:06:52.853365+00:00
# 2023-04-13 23:59:59.853426+00:00
4월 13일로 출력된 값을 DateTimeField로 DB에 저장하고, 그 시간을 Template으로 출력해 봅시다.
<div>{{ three_days_later | date:'Y.m.d H:i:s' }}</div>
위 날짜와 시간은 실제 템플릿에 출력된 결과를 캡처한 값입니다.
2023-04-13 23:59:59.853426+00:00 라는 값이 저장되었는데 출력될때는 2023.04.14 08:59:59로 출력됩니다.
위와 같은 현상이 생기는 이유는,
views.py에서 구한 시간은 UTC 기준으로 2023년 4월 13일 23시 59분 59초이고,
template에 출력되는 시간은 한국 시간 기준이기 때문에 UTC 기준에 +9 시간이 되어서 출력된 것입니다.
time zone과 함께 timestamp가 찍히는 DB를 통해 보면 아래 같이 저장됨을 확인 가능합니다.
Z는 시간대를 나타내는 문자로, UTC (Coordinated Universal Time)를 의미합니다.
결국, 계산은 UTC 기준으로 하고, 출력은 TIME_ZONE에 설정한 Asia/Seoul 기준으로 했기 때문에
그 만큼의 차이(9시간의 차이)가 생긴 것입니다.
아래와 같이 계산이 될 때의 시간과 (timezone.now().astimezone(pytz.timezone('Asia/Seoul')
출력될 시간의 기준(TIME_ZONE = 'Asia/Seoul')을 맞춰주면 원하는 값을 얻을 수 있습니다.
from dango.utils import timezone
from dateutil.relativedelta import relativedelta
import pytz # pip install pytz
timezone.now().astimezone(pytz.timezone('Asia/Seoul')) + relativedelta(days=3)
요약
* Django의 기본 시간 저장 기준: UTC
* 한국시간 = UTC 기준 + 9시간
* TIME_ZONE 은 출력되는 시간의 기준을 바꿀 뿐, 여전히 저장되는 기준 시간대는 UTC
+ Django에서 시간을 가지고 더하고 빼는 등의 조작을 할 때는 계산 과정에서부터 로컬 시간을 고려해서 해야 함
'Python > Django' 카테고리의 다른 글
Python Django - request session 이용하기 # get 에서 post로 data 넘기기 (0) | 2023.04.28 |
---|---|
Django: QuerySet to Json #QuerySet Json으로 보내기 # serializer # JsonResponse (0) | 2023.04.18 |
Django ManyToMany로 생기는 중간테이블(intermediate table)에 접근하기 # through # 중간테이블 정의 없이 (0) | 2023.03.30 |
Django 최신 데이터 가져오기# DateTimeField # latest # earliest (0) | 2023.03.26 |
Django: bulk create (0) | 2023.03.24 |