장고에서 timestamp 구하기

인터뷰 문제로 이런게 나온다면 어떨까

장고의 설정을

TIME_ZONE = 'Asia/Seoul'
USE_TZ = True

라고 했을때, 다음 코드 중 어느 것이 진짜 timestamp 를 돌려줄까.

datetime.utcnow().timestamp()    # 1번
timezone.now().timestamp()       # 2번

일단 정답은 2번이다.

순진하거나 똘똘한 날짜-시간 객체

파이썬의 날짜-시간 객체(datetime)에는 순진한(naive) 것과 똘똘한(aware) 것이 있는데, 멍청 순진함과 똘똘함은 타임존을 알고 있는지가 기준이다.

처음에 나온 문제에서 timezone.now()는 타임존을 알고 있는 aware datetime 을 돌려주지만, datetime.utcnow()는 타임존 정보가 들어있지 않은 naive한 녀석을 돌려주도록 구현되어있다.

>>> timezone.now()
datetime.datetime(2020, 5, 13, 7, 6, 28, 913469, tzinfo=<UTC>)
>>> datetime.utcnow()
datetime.datetime(2020, 5, 13, 7, 6, 29, 853238)

naive 하다해도, 타임존 정보가 들어있지 않을 뿐, 잘못된 값이 들어있는건 아니다. 여기까지는 문제가 없다.

타임스탬프와 UTC

문제는, 우리가 구하려는 timestamp 라는 녀석의 정의가

Unix timestamp is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT)

이므로 기준이 UTC여야 한다는 것.

만약 어떤 날짜-시각 객체가 있는데, 이 녀석이 naive한 경우의 timestamp()는 어떻게 구현해야 할까.

객체에 저장된 값이

  • UTC 라고 가정하거나
  • 지역시각이라고 가정하거나

둘중에 한가지 방법을 선택해야 한다.

파이썬의 타임스탬프

파이썬의 timestamp() 함수 구현은 타임존 정보가 없는 경우 주어진 객체가 지역시각일거라 가정한다.

그래서 이름만 보면

  • datetime.utcnow().timestamp() 는 UTC일 것 처럼 보이고
  • timezone.now().timestamp() 는 로컬 시각일 것 처럼 보이지만

실행해보면 아래 쪽의 timezone... 코드가 제대로 된 값을 돌려준다.

사족

만약 datetime 객체를 이용해야한다면 datetime.utcnow() 가 아닌 datetime.now(timezone.utc)를 사용해야 timestamp()가 제대로 동작한다.

참고

에필로그

매번 타임존 문제를 헷갈리다가 이번에 naiveaware를 보라는 코멘트에 찔려서 공부안하는 나를 부끄러워하며 조사한 결과임. ㅜㅜ