Home » 레퍼런스 » PYTHON » 파이썬 datetime now 함수는 어떻게 동작할까요?

파이썬 datetime now 함수는 어떻게 동작할까요?

파이썬 datetime now 함수의 동작을 간략하게 알아 보겠습니다. 몰랐던 부분도 있고 잘못 알면 헷갈릴 만한 것도 있습니다.


datetime now 함수의 코드 보기

먼저, now는 현재 시각을 얻어오는 함수입니다. tz 인자가 들어가면 시간대 정보가 들어간 것이, 그렇지 않으면 naive datetime이 리턴되게 됩니다.

[그림 1] now 함수의 내부

먼저, _time.time() 함수로 unix time을 얻어옵니다. 다음에, fromtimestamp를 호출합니다. unix time은 utc 1970년 1월 1일 0시 0분 0초부터 경과된 시각을 초 단위로 돌려줍니다. 1805번째 줄을 보면, fromtimestamp를 호출하게 됩니다. 이 함수를 보겠습니다.

[그림 2] fromtimestamp 함수

이 함수는 tz가 None이 아니라면 true를, 아니면 false를 _fromtimestamp에 넘깁니다. 2번째 인자는 utc입니다.

[그림 3] _fromtimestamp 함수의 일부

이 함수를 보면, converter가 있어요. utc가 true이기 때문에 gmtime을 호출합니다.

[그림 4] gmtime 함수

gmtime은 utc time을 UTC 타임존이 적용된 시각으로 바꿉니다. 그리고 tz도 None이 아니기 때문에, 1782번째 줄에 걸리게 됩니다.

[그림 5] datetime 코드의 일부

그렇기 때문에, 1782번째 줄에 걸리고, tz의 fromutc가 호출되게 됩니다. 이 때, self에는 tz에 대한 정보가 들어가게 됩니다. 여기까지 플로우 차트로 정리해 보겠습니다.

여기서 중요한 것은 unix_time을 utc time으로 변경한다는 것입니다. 여기까지 now에 넘겨준 tz는 의미가 없습니다.


fromutc 함수 내부로

이제, 이 함수의 내부로 들어가 보겠습니다.

[그림 6] fromutc 함수

대략적인 로직을 보면, replace의 tzinfo를 None으로 두어서 시간대 정보만 빼 버립니다. 다음에, 수상한 이진 탐색 알고리즘을 호출한 다음에, 다시 replace 함수를 호출하게 됩니다. 여기서 중요한 부분은 1번째로 호출하는 replace 입니다.

이 tzinfo를 None으로 돌려버린 경우, 어떻게 동작하는가?

간단합니다. 그냥 타임존 정보를 없애버립니다. 고로, +08:28로 들어왔던, +09:00으로 들어왔던, +10:00으로 들어왔던 타임존 정보 자체가 의미가 없어져 버립니다. 이 상황에서, 밑에 줄이 실행됩니다.

[그림 7] self의 _utc_trans_times에 있는 것들

이 배열을 보면, 30여개의 데이터가 있음을 볼 수 있어요. 무엇인지는 모르겠지만, datetime 오름차순으로 정렬되어 있음을 알 수 있어요. 이 시기에 뭔가 바뀐 것이 있을까요?

[그림 8] self_transition_info 배열

이는, self_transition_info를 보면 알 수 있습니다. 0번째에는 LMT, 1번째에는 KST, 2번째에는 JST 등으로 변했음을 알 수 있는데요. seconds가 30480, 30600 등으로 변했음을 볼 수 있어요. 이는 한국 표준시가 바뀌었다는 것을 의미합니다. 실제로 1911-12-31 15:30:00과 대응되는 데이터가 32400인데, 1912년 1월 1일에 한반도 표준시가 변경되었습니다.

이 이벤트 배열에 현재 시간과 대응되는 올바른 시간대 정보가 있는 위치를 찾습니다.

[그림 9] 2024년에 대응되는 위치 찾기

2024년은, 1988년 10월 8일 이후이므로, _utc_trans_times의 29번째 위치입니다.

[그림 10] 시간대에 대한 정보

이 정보를 찾았더니 timedelta가 9:00:00 입니다. utc보다 9시간 빠르다는 의미입니다. 1번째 timedelta는 다음에 언급할 예정이니, 여기에서는 넘어가도록 하겠습니다. 이 정보를 바탕으로, 9시간을 더한 다음에, timezone 정보를 넣게 됩니다.

여기까지 흐름을 정리해 봅시다.

utc time이 들어옵니다. tz 정보도 같이 들어왔을 겁니다. 그런데, 뒤에 들어있는 tz는 의미가 없습니다. 왜? utc 1970년 1월 1일 0시 0분 0초부터 경과된 초만 들어왔기 때문입니다. 고로, tz=None으로 타임존 정보를 제거합니다.

다음에, (dt + inf[0]).replace(tz=tz) 부분입니다. 이 부분은 어떤가?

inf[0]은, 현재 적용된 지역의 시간대입니다. 예를 들어, 서울은 1988-10-08 17:00:00 일 때 시간대 정보가 마지막으로 바뀌었습니다. 이 정보를 얻어와서, 현재의 서울 시간대로 반영합니다. 다음에, 이 정보를 tz에 추가해서 돌려줍니다.


예제 보기

이제 파이썬 datetime now 예제를 보겠습니다.

[그림 11] 예제 1번 프로그램

예제 1번을 보겠습니다. pytz로 서울의 시간대 정보를 얻어옵니다. 이건 +08:28로 되어 있습니다. 그런데, 제대로 동작합니다. 왜?

  • now 함수는 unix_time을 얻어와서 utc 시간으로 바꿉니다.
  • 이를, 현재 적용된 서울 시간대를 가지고 변환합니다.

결국, 중요한 것은 unix_time을 얻어와서 기준이 되는 utc 시간으로 바꿔버렸습니다. 고로, 잘못된 정보의 timezone이 들어와도 무시됩니다. 그 정보가 연산 과정에서 잠시 없어지기 때문입니다. 다음에, 호출된 현재 시각에 대응되는 서울의 timezone 정보를 얻어와서 반영했습니다. 따라서, 의도대로 동작합니다. 결과를 볼까요?

[그림 12] 예제 1의 결과

제가 오후 7시에 실행시켰고, 시간대 정보인 +09:00도 제대로 나왔네요.

[그림 13] 예제 2번 프로그램

시간대 정보를 안 주면 어떻게 동작할까요? 이 경우 로컬 시간이 나오게 됩니다.

[그림 14] 예제 2의 결과

제가 이 프로그램을 실행시킨 것은 오후 8시 24분 이였습니다. 시간대가 빠진 datetime이 나오게 됩니다.

Leave a Comment

14 + 15 =