model에서 DateTimeField 한국 시간으로 설정하기

# models/diary.py

class Diary(models.Model):

    created_at = models.DateTimeField(auto_now_add=True)

이렇게 model을 만들어 model의 instance를 만들게 되면 created_at 필드에는 기본적으로 UTC 시간이 들어가게 된다.

그래서 일단 settings에서 TIME_ZONE 값만 바꾸어 보았다.

# internationalization.py

# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Seoul'

USE_I18N = True

USE_L10N = True

USE_TZ = True  

하지만 $ python manage.py runserver 할 때의 시간만 한국 시간으로 나올 뿐 여전히 model의 created_at에는 UTC 시간이 들어가였다.

하지만 내가 만들 일기 서비스에는 한국 시간이 들어가야 하므로 이 부분을 수정하기 위해 구글링을 하였다. 그 결과 pytz 문서를 참고하여 아래와 같이 한국 시간으로 반환해주는 별도의 property를 추가함으로써 해결할 수 있었다.

# diary.py

from django.db import models  
from django.conf import settings  
from pytz import timezone


class Diary(models.Model):

    created_at = models.DateTimeField(auto_now_add=True)

    @property
    def created_at_korean_time(self):
        korean_timezone = timezone(settings.TIME_ZONE)
        return self.created_at.astimezone(korean_timezone)

그리고 다음의 test 코드를 통해 원하는 결과가 나옴을 확인할 수 있었다. test 코드를 짜는 데 한참 더 많은 시간이 걸렸다.

# test_models.py

from django.test import TestCase  
from django.contrib.auth import get_user_model  
from datetime import datetime  
import pytz

from diaries.models import Diary


class DiaryModelTestCase(TestCase):

    def setUp(self):

        # Create a user
        self.user = get_user_model().objects.create_user(
            username="test_username",
            password="test_password",
        )

        # Create a diary
        self.diary = self.user.diary_set.create(
            content="content",
        )
        # Diary was created at 2016/06/30 15:18:38,(tzinfo='UTC')
        self.diary.created_at = datetime(2016, 6, 30, 15, 18, 38, tzinfo=pytz.utc)

    def test_diary_model_should_have_created_at_korean_time(self):

        # Korean time = UTC + 9 hours
        self.assertEqual(
            self.diary.created_at_korean_time.strftime("%Y-%m-%d %H:%M:%S"),
            '2016-07-01 00:18:38',
        )

아래부터는 진정한 해결법입니다. 위의 글 모두 무시하셔도 좋습니다.

하지만 안수찬 강사님 덕분에 내가 한 이 모든 것이 뻘짓이었다는 것을 알게 됐다. 그냥 간단히 아까 settings에서 USE_TZFalse로 바꿔주면 해결되었다...

장고 공식 문서에 보면 TIME_ZONE에 대해서 아래와 같이 나와있다.

When USE_TZ is False, this is the time zone in which Django will store all datetimes. When USE_TZ is True, this is the default time zone that Django will use to display datetimes in templates and to interpret datetimes entered in forms.

즉, USE_TZTrue일 때는 templates, forms에서의 datetime에만 내가 설정한 TIME_ZONE이 적용된다. 따라서 models의 datetime에는 이 부분이 적용되지 않았기 때문에 원래의 default time zone인 'UTC' 값으로 계속 설정되었던 것이다.

나는 models에서도 내가 설정한 TIME_ZONE 값을 적용하고 싶기 때문에 이 부분을 False로 바꾸어 주었다.

# internationalization.py

# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Seoul'

USE_I18N = True

USE_L10N = True

USE_TZ = False