UTC 시간과 파이썬 : 기본편

GMT, UTC 란


GMT (Greenwich Mean Time) 는 영국 런던의 그리니치 천문대에서 태양 위치를 측정하여 만든 표준시간 입니다.

UTC (Coordinated Universal Time) 는 GMT에 기반을 두고 있으나, 정밀한 원자시계를 사용하여 보다 정확하게 조정된 시간입니다. 1972 년 1월 1일부터 시행된 국제 표준시이며, 1970년 1월 1일 자정을 0 밀리 초를 기준 삼아 시간의 흐름을 밀리 초로 누적 계산합니다. 이러한 누적시간을 타임스탬프(TimeStamp) 라고 합니다.

UTC 는 컴퓨터 시스템과 네트워킹에서 데이터 기록, 로그 관리, 시간 동기화 등에 중요하게 사용됩니다. 아래와 같이 여러가지 프로그래밍 언어에서 간단한 코드를 통해 UTC 가 사용되고 있음을 확인 할 수 있습니다.

js
const Jan01_1970 = new Date(0);
Jan01_1970.valueOf() // 0

const now = new Date();
now.valueOf()        // 170........ 1970-01-01 이후 누적 밀리 초
python
from datetime import datetime

now = datetime.now()
print(now.timestamp()) # 170........ 1970-01-01 이후 누적 밀리 초

ISO 8601


그렇다면 UTC 는 어떻게 표기 해야 할까요? 날짜, 시간, 그리고 시간대를 명확하고 일관된 형식으로 표현하기 위해 ISO 8601 표준을 따르면 됩니다. UTC 시간은 ISO 8601 표준에 따라 아래와 같이 표기될 수 있습니다.

2023-12-24T15:00:00Z

2023-12-24T15:00:00+00:00

시간대 오프셋


많은 국가와 지역은 고유의 표준 시간대를 가지고 있으며, 이는 UTC 오프셋으로 정의됩니다. 예를 들어, 한국 표준시(KST)는 UTC+9, 뉴욕(동부 표준시, EST)는 UTC-5입니다.

그림 1. UTC Map

지역 시간은 UTC 시간에 해당 지역의 오프셋을 더하거나 빼서 계산합니다. 예를 들어, UTC 시간이 0인 (= UTC) 영국이 크리스마스 이브 = 2023-12-24 일 15:00 시 이면, 시간대 오프셋이 +09:00한국은 크리스마스 당일 = 2023-12-25 일 0시 입니다.

2023-12-24T15:00:00Z

2023-12-25T00:00:00+09:00

파이썬에서 UTC


Python에서 UTC 시간을 다루기 위한 datetime 모듈 주요 함수들은 다음과 같습니다.

datetime.now()


현재 시스템의 로컬 시스템 시간을 반환합니다. 기본 호출(인수 없이)은 시간대 정보가 없는 naive datetime 객체를 반환합니다. 즉, datetime.now()로 생성된 datetime 객체는 시간대를 알 수 없습니다. UTC 가 있는 구체적인 시간대와 비교하거나 변환하는 것이 명시적으로는 불가능합니다. 시간대 정보는 tzinfo 속성으로 확인 가능합니다.

python
from datetime import datetime

now = datetime.now()

print(now)        # 2023-12-25 00:00:00.000000
print(now.tzinfo) # None

datetime.utcnow()


이 함수는 현재 UTC 시간을 반환합니다. 하지만 이 함수도 시간대 정보가 없는 naive datetime 객체를 반환합니다. 즉, 제대로 된 UTC 활용이 어렵습니다. 그리고 python 3.12 버젼 부터는 deprecated 되었기 때문에 사용하지 않는 것을 권장 합니다.

python
from datetime import datetime, UTC

utc_now = datetime.utcnow()

print(utc_now)        # 2023-12-24 15:00:00.000000
print(utc_now.tzinfo) # None

어웨어와 나이브 객체


날짜와 시간 객체는 시간대 정보를 포함하는지에 따라 어웨어(aware)와 나이브(naive)로 분류될 수 있습니다.

어웨어(aware)

어웨어 객체는 다른 어웨어 객체와의 상대적인 위치를 파악할 수 있습니다. 이는 일광 절약 시간(=DST), 썸머 타임 적용 또한 가능하게 합니다. 즉, 명확한 시간의 사용 및 계산이 가능합니다.

나이브(naive)

나이브 객체는 다른 시간과 상대적인 위치를 파악할 충분한 정보를 포함하지 않습니다. 나이브 객체가 UTC, 지역 시간 또는 다른 시간대의 시간 중 어느 것을 나타내는지는 순전히 프로그램에 달려있습니다. 나이브 객체는 이해하기 쉽고 작업하기 쉽지만, 시간을 다루는 로직에서 문제가 생길 수 있습니다.

timezone 추가하기


그렇다면 UTC 오프셋이 올바르게 적용된 시간 객체를 만드는 방법은 무엇일까요? timezone 이라는 오프셋을 의미하는 객체를 시간을 생성 할때 추가해주면 됩니다. UTC 0 을 의미하는 timezone.utc 또는 python 3.12 버젼에서는 UTC 라는 별도의 상수값이 추가되어 이를 사용해도 됩니다.

python
from datetime import datetime, timezone, UTC

now = datetime.now(timezone.utc)

print(now)        # 2023-12-24 15:00:00.000000+00:00
print(now.tzinfo) # UTC

+09:00 한국 오프셋 설정


UTC+00:00 이외의 시간대를 표시 할 때는 오프셋 시간 만큼 timedelta 객체를 사용하여, timezone 객체를 직접 생성해서 사용하면 됩니다. +09:00 끝에 시간대 오프셋이 추가되어 출력되는 것을 확인 할 수 있습니다. 또한 tzinfo 속성값이 설정 된것을 확인 가능합니다.

python
from datetime import datetime, timezone, timedelta

tz = timezone(timedelta(hours=9))
now = datetime.now(tz)

print(now)        # 2023-12-25 00:00:00.000000+09:00
print(now.tzinfo) # UTC+09:00

pytz 라이브러리


여러나라의 timezone 을 하나씩 직접 시간 오프셋을 이용해서 만든다고 생각해봅시다. 어떤 나라의 어떤 도시는 어떤 오프셋을 가지는지 일일히 알아야 합니다. 이때 약 500 개 이상의 UTC 정보를 제공해주는 pytz 라이브러리를 사용하면 UTC 를 포함한 다양한 시간대를 쉽게 다룰 수 있습니다.

pip install pytz
python
from datetime import datetime
from pytz import timezone, all_timezones

tz = timezone("Asia/Tokyo")
now = datetime.now(tz)

print(now)           # 2023-12-25 00:00:00.000000+09:00
print(now.tzinfo)    # Asia/Tokyo
print(all_timezones) # 지원하는 시간대 문자열 확인 가능

UTC 정리


UTC 는 시간을 국제 표준시이며, 많은 시스템과 프로그래밍에서도 이를 사용하고 활용하고 있습니다. UTC 를 정확하게 표기 하기 위해서는 ISO 8601 를 따르면 됩니다. 하지만 위에서 출력된 결과는 어떤가요? 위에서 봤던 코드에는 함정이 있습니다. 다시 한번 잘 보시길 바랍니다.

과연? ISO 표준을 잘 준수해서 표현되고 있는지…

# 코드에서 만든 시간
2023-12-24 15:00:00.000000+00:00
2023-12-25 00:00:00.000000+09:00

# ISO 표준
2023-12-24T15:00:00.000000Z
2023-12-25T00:00:00.000000+09:00

날짜와 시간 사이에 구분 문자열인 T 가 빠져있는 것을 확인 할 수 있습니다. 이렇듯 표준과 다른 사소한 표기가 가져오는 몇 가지 문제가 있습니다. 🥲

  1. 날짜와 시간 구분자
  2. 시간대 표현법
  3. 시간대 오프셋을 고려해서 계산

실제 업무에서 구현하면서 만났던 문제는 🔗다음편 : UTC 시간과 파이썬 : 유의사항 에서 적도록 하겠습니다.

python UTC