Python DateTime 관련 팁

2023년 2월 22일 수정

이 글은 Python의 날짜나 시각을 다루는 방법과 관련된 내용들을 정리하기 위한 글이다.

시각 수정하기

replace 메서드를 이용하면 원하는 데이터를 수정할 수 있다. 예를 들어 초(seconds)에 소수점 단위가 보기 싫다면 microsecond를 0으로 넣어버리면 된다.

from datetime import datetime

datetime.now().replace(microsecond=0)

시간차를 초단위로 얻기

timedelta 인스턴스에는 total_seconds() 메서드가 있다. 이를 이용해 볼 수 있다.

(datetime_to - datetime_from).total_seconds()

원하는 타임존의 현재 시각 구하기

예를 들어 한국 기준 시각(GMT+9)을 구하려면 아래 처럼 할 수 있다.

from datetime import datetime, timezone, timedelta

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

타임존 바꾸기

예를 들어 타임존을 UTC로 바꾸려면 pytz 패키지의 힘을 빌어 아래와 같이 할 수 있다.

import pytz
from datetime import datetime

datetime.now().astimezone(pytz.UTC)

물론 astimezone()pytz.UTC 를 위한 억지 예제일 뿐, 위와 같은 경우는 그냥 utcnow() 를 쓰는게 나을 것 같다.

pytz 는 기본 패키지가 아니기 때문에 별도로 의존성을 추가해야 한다는 점을 잊지 말자.

타임존 교체하거나 없애기

위의 타임존 바꾸기는 해당 타임존에 맞게 시간을 수정하는데, 특별한 경우 시간 수정 없이 타임존 표기만 바꾸거나 없애고 싶을 때가 있다. 이럴 때도 replcae 메서드를 활용할 수 있다.

datetime.now().replace(tzinfo=pytz.UTC)

값을 None 으로 넣으면 아예 타임존을 삭제할 수 있다.

datetime.utcnow().replace(tzinfo=None)

타임존 삭제를 언제 쓰느냐 궁금할 수도 있는데, ISO Format으로 변경할 때 오프셋을 표시하지 않으려고 할 때 등이 있다.

ISO 포맷 파싱하기

두 가지 방법을 사용할 수 있다. 하나는 datetime 모듈의 메서드다.

from datetime import datetime
datetime.fromisoformat('2021-05-10T10:16:00+00:00')

다른 하나는 dateutilparse 다.

from dateutil.parser import parse
parse('2021-05-10T10:16:00+00:00')

퍼포먼스면에서 보자면 fromisoformat 쪽이 압도적으로 빠르다. 아마도 parse 는 ISO 포맷 전용 파서가 아니기 때문에 그렇지 않을까 유추된다.

datetime을 ISO 포맷 문자열로 변환하기

isoformat() 메서드를 사용할 수 있다.

from datetime import datetime
datetime.now().isoformat()

타임존을 얻으려면 아래와 같이 할 수 있따.

from datetime import datetime, timezone
datetime.now(timezone.utc).isoformat()

설마 Python 2.x를 아직도 쓰는 사람은 없으리라 믿는다.

offset-naive와 offset-aware 간의 비교

datetime 오브젝트끼리 비교하는 경우, 예를 들어 아래와 같은 경우

dt_a >= dt_b

특정한 상황에서 아래와 같은 오류를 겪을 수도 있다.

TypeError: can't compare offset-naive and offset-aware datetimes

보통 이런 경우 두 오브젝트 중 하나는 timedelta 를 이용해 시각 정보가 바뀐 경우나, 혹은 타임존이 명확하지 않거나 다른 경우 등에 발생할 수 있다.

쉽게 해결하려면 그냥 타임존을 똑같이 맞추면 된다. 아래와 같은 식으로 말이다.

dt_a.replace(tzinfo=pytz.UTC) >= dt_b.replace(tzinfo=pytz.UTC)

물론 필요한 객체만 replace 해도 된다.