python utcnow 함수는 datetime에 있습니다. 이 함수는 현재 시각을 utc 시간으로 바꿔줍니다. 그런데, 문서를 보면 warning이 쓰여져 있는데요. 어떤 이유일까요? 간단한 예제 프로그램을 차근차근 분석해 보면서 알아보도록 하겠습니다.
코드 조각 훑어보기 1
먼저, 이 코드를 보겠습니다.
3번째 줄에는 datetime.utcnow()가 있습니다. 4번째 줄에는 datetime.now(timezone.utc)가 있습니다. 둘 다, utc timezone의 시각을 얻어옵니다. 차이점은 무엇인지 아래 실행 결과를 보겠습니다.
저는 이 프로그램을 서울 시각으로 21시 40분에 실행시켰습니다. utc+9이므로, utc 시각으로는 12시 40분이 됩니다. 중요한 것은 t1은 뒤에 +00:00이 붙지 않았고, t2는 뒤에 +00:00이 붙었다는 것입니다. 이 둘의 차이는 timezone 정보가 뒤에 붙는지 여부입니다. python utcnow 함수는 시간대 정보가 붙지 않는 datetime 객체를 돌려줍니다. now 함수에 시간대 정보를 넘겨서 주면, 시간대 정보가 뒤에 붙게 됩니다. 이를 정리하면 아래와 같습니다.
- python utcnow 함수는 timezone 정보가 붙지 않은 datetime 객체를 리턴
- python now 함수에 시간대 정보를 넘겨주면, timezone 정보가 붙은 datetime 객체를 리턴
어떤 사람이 현재 시각이 11시라고 이야기했습니다. 이 사람이 어느 지역에 있는지 말해주지 않는다면 정확한 시간을 모릅니다. 왜? 내가 서울에 있지만, 시각을 알려준 사람은 뉴욕에 있을 수도 있기 때문입니다. 그런데, 어떤 사람이 뉴욕의 현재 시각은 11시야. 라고 이야기 해 주면 어떨까요? 시간대 차이를 이용해서 계산할 수 있게 됩니다.
naive datetime은 전자의 상황을, aware datetime은 후자의 상황을 말합니다. 여기까지 이해하셨다면, 코드 조각 2로 넘어갑시다.
코드 조각 훑어보기 2
이제 이 코드를 봅시다.
그림 3의 코드 조각 2는 얻어온 시각에 대한 정보를 시간대 정보가 있는 singapore 시간으로 바꿉니다. astimezone은 여기에, timezone 정보를 추가합니다. 코드 조각 1에서 t1과 t2는 아래와 같은 정보가 있었습니다.
- 12시 40분입니다.
- utc 시간대로 12시 40분입니다.
astimezone 으로 시간대 정보가 있는 singapore 시간 정보로 바꾸면 어떻게 될까요? 일련의 과정을 이해해 봅시다.
먼저 입력된 datetime의 timezone을 불러옵니다. 이것과 utc의 timezone 차이를 계산해서 utc 시간으로 변경시킵니다. 댜음에, 변경할 시간대와 utc의 timezone 차이를 계산합니다. 이것까지 계산하면, 내가 원하는 시간대의 시각으로 변환할 수 있습니다.
예를 들어, utc 시간대로 12시 40분인 시각을, singapore 시간대로 변경한다 해 볼게요.
먼저, 들어온 정보를 utc 시간으로 변경해야 합니다. 그런데, 들어온 정보가 utc 시간대였어요. 차이가 없네요? 따라서, utc 시간으로 12시 40분이라는 정보로 바뀝니다.
이제, 바꿀 시간대와 utc의 차이를 구합니다. 싱가폴과 utc의 차이를 빼면 8시간입니다. 싱가폴이 8시간 빠릅니다. 고로, 이 시각은 싱가폴 시간으로는 20시 40분이 됩니다. timezone 정보가 있었기 때문에, utc 기준으로 무난하게 계산할 수 있습니다.
반면, timezone 정보가 없는 경우는 이야기가 달라집니다.
timezone이 없다면?
시간대 정보가 없는 naive datetime이 들어왔다면 어떻게 동작할까요? 이 경우, 로컬에 설정되어 있는 시간대로 가정합니다. 무슨 이야기인가?
- 12시 40분입니다.
라는 정보가 t1에 있었습니다. 이 정보를, astimezone에서는 로컬에 설정된 서울 시간대로 12시 40분이라고 가정합니다.
따라서, 이 과정에서 12시 40분이라는 정보는 utc 시각으로 3시 40분이구나. 라는 정보로 잘못 전달되게 됩니다. 이 문제의 근본적인 원인은 아래와 같습니다.
- timezone 정보가 생략되었습니다.
- 그래서 해당 시각이 항상 로컬 시간대인 서울 시간대일 거라고 잘못 가정합니다.
이제, 아래 과정을 수행합니다.
utc 시각으로 3시 40분이라는 정보는 singapore 시간대로 변경하는 과정에서 아래와 같은 정보로 변경됩니다.
- 싱가폴 시각으로
- 11시 40분입니다.
실행 결과는 아래와 같습니다.
밑의 두 줄만 보시면 됩니다. timezone이 생략된 시간대는 의도치 않은 결과를 보일 수 있으니, 왠만하면 aware datetime을 사용하는 게 좋겠습니다.