[ISO] ISO 8601과 UTC 그리고 python 예제

python에서 datetime class를 이용할 때, javascript에서 Date class를 이용할 때 그리고 java에서 Date class를 이용할 때 종종 보았던 날짜 표시 형식과 그 의미에 관해서 간략하게 알아본다.


UTC와 GMT

UTC

UTC는 Coordinated Universal Time의 줄임말로 1972년 1월 1일부터 시행된 국제 표준시입니다. 이 UTC는 국제 원자시와 윤초 보정을 기반으로 표준화 되어있습니다. 즉, 세계에서 시간을 표현하는 표준시라고 보면됩니다.

GMT

GMT는 Greenwich Mean Time의 줄임말로 그리니치 평균시라고 불리며 런던을 기점으로 하고 웰링턴에서 종점으로 설정 되는 협정 세계시입니다.

UTC vs GMT?

결론부터 말하면 UTC와 GMT는 일상에서는 공통으로 같은 시간을 나타냅니다.(정확하게 들어가면 UTC가 더 정확한 시간을 표현합니다.) 1972년 1월 1일부터 UTC라는 세계 협정시가 사용되었으며 이는 먼저 사용되던 GMT와 기준시가 같기에 요즘날에 혼용해서 사용하게 되었습니다.


UTC를 기준으로 한 시간의 표현과 Timezone

Timezone

이제 위에서 UTC라는 국제표준시로 시간을 정한다는 부분을 설명드렸습니다. 그런데 국가마다 사용하는 시간이 다르기 때문에 공통된 시간대로 묶은 특정 지역을 Timezone이라고 합니다.

우리나라의 경우에는 ISO 8601에 따르면 2017-03-16T17:40:00+09:00와 같은 형식으로 표시된다고 합니다.

아래서 설명을 하겠지만 뒤에 +09:00부분을 통해서 UTC기준시로 9시간이 추가된 시간대라는 것을 표현합니다.

Timezone에 관련된 링크는 다음과 같습니다. Wikipedia - Timezone


ISO 8601

정의

UTC 그리고 Timezone과 함께 문자열의 형태로 시간을 표현하는 방법을 기술해놓은 표준입니다.

몇가지 원칙

  • 년/월/일T시:분:초 처럼 왼쪽에서 오른쪽으로 갈수록 작은 단위어야 합니다.
  • 날짜와 시간은 포맷을 맞추기 위해 0을 붙입니다. EX) 4월 -> 04월
  • 위의 2가지가 중요하다고 생각하며 나머지 3가지는 링크를 참고하시길 바랍니다.Wiki

형태

가장 기본적인 형식(날짜와 시간)은 아래와 같습니다.

2017-03-16T17:40:00+09:00
  • 날짜: 년-월-일의 형태로 나와있습니다.
  • T: 날짜 뒤에 시간이 오는것을 표시해주는 문자입니다.
  • 시간: 시:분:초의 형태로 나와있으며 프로그래밍 언어에 따라서 초 뒤에 소수점 형태로 milliseconds가 표시되기도 합니다.
  • Timezone Offset: 시간 뒤에 ±시간:분의 형태로 나와있으며 UTC기준시로부터 얼마만큼 차이가 있는지를 나타냅니다. 현재 위의 예시는 한국시간을 나타내며 UTC기준시로부터 9시간 +된 시간임을 나타냅니다
  • (Z or +00:00): UTC기준시를 나타내는 표시이며 “+00:00”으로 나타내기도 합니다.


Python에서 datetime과 timezone표시

파이썬에서 간단하게 ISO 8601에 따라서 시간을 표시해보는 간단한 코드를 보겠습니다. datetime class를 이용합니다.

특별한 명시 혹은 timezone을 설정해주지 않으면 System의 시간과 timezone에 따라서 시간을 나타내게 됩니다.

test.py

import datetime

#.now() -> 현재 local time
print(str(datetime.datetime.now()))
#.utcnow() -> utc 기준시
print(str(datetime.datetime.utcnow()))
Taewooui-MacBook-Pro:Documents taewoo$ python test.py
2017-03-16 19:55:28.084217
2017-03-16 10:55:28.084274

위와 같이 현재 시간과 UTC 시간이 나오지만 UTC에 대한 정보가 생략되어있습니다. 즉, +00:00과 같은 포맷이 없는데다가 T가 없고 띄어쓰기가 있는걸로 보아 완전한 ISO 8601의 형태가 아닙니다.


test_datetime_in_iso_format.py

import datetime

print(str(datetime.datetime.now().isoformat()))
print(str(datetime.datetime.utcnow().isoformat()))
Taewooui-MacBook-Pro:Documents taewoo$ python test_datetime_in_iso_format.py
2017-03-16T20:02:57.224509
2017-03-16T11:02:57.224592

T도 있고 붙여써서 ISO 8601 형태에 맞지만 아직 timezone의 정보가 들어있지 않습니다.

파이썬 datetime 자체로는 timezone을 지원하지 않습니다. 그래서 pytz와 같은 모듈을 써야합니다.


test_datetime_with_pytz.py

import datetime
import pytz

print(str(datetime.datetime.now(tz=pytz.utc).isoformat()))
Taewooui-MacBook-Pro:Documents taewoo$ python test_datetime_with_pytz.py
2017-03-16T11:08:12.216857+00:00


JSON string date format => Python datetime

JSON은 string의 형태로 datetime의 값이 날아오게 됩니다. 이 때 ISO 8601에 따른 형식일 때 어떻게 python datetime 객체로 바꾸는지에 대한 코드입니다. dateutil.parser를 이용하면 비교적 쉽게 파싱이 가능합니다 :)

import dateutil.parser

print(str(dateutil.parser.parse("2017-03-16T11:08:12.216857+00:00")))
print(str(dateutil.parser.parse("2017-03-16T11:08:12.216857Z")))
2017-03-16 11:08:12.216857+00:00
2017-03-16 11:08:12.216857+00:00

위처럼 UTC 시간으로 나오며 뒤에 타임존 부분도 추가되어있음을 확인 할 수 있습니다. 실제로 테스트 코드도 pytest로 돌려본 결과 같다고 assert를 실행하였을 때 결과가 나왔습니다


하지만 UTC 표준시로 나와있으며 타임존이 표시가 되어있지만 현재 제 지역의 타임존이 추가 되어있지 않습니다ㅠㅠ

이제 현재 컴퓨터에 따른 Timezone을 추가해봅시다.

버전에 따라서 여러 방법이 있지만 pytz를 통해서 2와 3에서 다 사용 할 수 있는 코드는 아래와 같습니다.

test.py

import dateutil.parser
import pytz

# JSON으로 들어온 문자열을 python datetime으로 변환
date=dateutil.parser.parse("2017-03-16T11:08:12.216857+00:00")

# Timezone을 설정
local_timezone = pytz.timezone('Asia/Seoul')

# Timezone에 따라서 새로운 date형식을 변경
local_date = date.replace(tzinfo=pytz.utc).astimezone(local_timezone)

# 출력
print(local_date.isoformat())
Taewooui-MacBook-Pro:Documents taewoo$ python test.py
2017-03-16T20:08:12.216857+09:00


왜 UTC와 ISO 8601을 따라야 할까?

ISO 8601에 따르면 파싱을 할 수 있는 라이브러리가 많으며 전체적으로 호환이 되는 부분이 많습니다. 무엇보다 현재 적용하고 있는 프로젝트와 이전과 비교되면서 느낀거지만 timestamp나 정수형으로 저장이 되어있다면 어디 기준으로 기록된 시간인지에 대한 정보가 없습니다. 이러한 부분에서 보면 불편함이 있더라도 DB에 저장하거나 할 때 각 언어가 지원해주는 날짜 및 시간관련 코드들을 적극 사용하는 부분이 여러 호환에 있어서 이득이라 여겨집니다.