Python에서 Datetime과 Timezone 다루기

Datetime은 python에서 날짜와 시간을 표현하는 아주 유용한 패키지입니다.

대다수의 데이터베이스의 시간은 기본적으로 UTC 시간을 기준으로 설정이 되어 있습니다.
국내에서만 서비스를 한다고 하면 데이터베이스의 시간을 한국표준시간(KST)로 설정할 수도 있습니다. 하지만 글로벌 서비스의 경우에는 해당 유저에 따라 적절한 시간대를 보여주어야 할 경우도 생기게 됩니다.

이럴때에는 데이터베이스에 UTC시간으로 저장을 해놓고 데이터를 가공할 때 Timezone을 원하는 지역의 Timezone으로 변경하면 됩니다.

이제 그 방법을 알아보도록 합니다.

Timezone 변경하기

from datetime import datetime
from pytz import timezone

# 현재 시간을 UTC로 표시한다
now_utc = datetime.now(timezone('UTC'))

# UTC 시간을 KST로 변경한다
now_kst = now_utc.astimezone(timezone('Asia/Seoul'))


Datetime의 시간차이 구하기


Timezone 변경 뿐만 아니라, Datetime간의 시간 차이를 계산해야 할 경우도 있습니다.

예를 들어, 다음과 같은 기능을 구현할 때 시간 차이를 계산해야 합니다.

  • 관리자 페이지에서 동영상을 예약된 시간에 업로드하는 기능을 구현


위와 같은 경우 스케줄러를 통해 일정간격으로 예약된 시간이 되었는지 확인하는 로직이 필요합니다.

python의 Datetime에서 기본적으로 제공하는 연산자만 사용해도 위의 기능을 충분히 구현할 수 있습니다.

아래의 구현은 동영상을 예약 업로드하는 함수를 구현한 것입니다.

# 동영상 예약 업로드를 처리하는 메서드
def handle_post_video(self):
video_list = Video.objects.filter(transcoding_status='complete', is_posted=False)
for video in video_list:
# 두 datetime의 형식이 같아야 기본 연산자로 비교가 가능합니다
post_time = video.post_time.astimezone(timezone("Asia/Seoul"))
now = datetime.now(timezone("Asia/Seoul"))
# 현재 시간이 동영상 예약 시간을 지나면 동영상을 업로드한다
if post_time <= now:
upload_video(video)


위에서 알 수 있듯이 <, =, >와 같은 기본 연산자를 통해 datetime의 시간 차이를 판별할 수 있습니다.
이때 주의해야 할 점이 있는데 바로 비교하는 두 datetime의 형식이 같아야 한다는 점입니다.

datetime에는 아래의 두 형식이 존재합니다.

  • Offset-Naive Datetime
  • Offset-Aware Datetime


두 형식의 큰 차이점은 바로 Timezone 정보가 존재유무입니다.

전자의 경우 Timezone 정보가 없고 후자는 존재합니다.
이 때문에 형식에 차이가 생기고 같은 형식이 아닌 datetime은 비교 연산이 불가능합니다.

# Offset-Navie한 datetime
now_naive = datetime.now() # Local Timezone 기준으로 시간정보가 리턴됩니다

# Offset-Aware한 datetime
now_aware = datetime.now(timezone("Asia/Seoul"))

Python에서는 Datetime을 다룰 때 아래의 규칙들을 준수할 것을 권장합니다.

  • 항상 Offset-Aware한 Datetime을 사용할 것
  • 데이터베이스에 UTC 기준으로 시간 정보를 저장하고 사용자에게 데이터를 건네줄 때 Timezone을 변경할 것
  • ISO 8601 표준에 해당하는 날짜 표기 방법을 사용할 것

따라서 Datetime을 비교할 때에도 Offset-Aware 형식의 Datetime을 사용하면 됩니다. 

댓글()