파이썬 datetime, dateutil : 생각보다 어려운 시간 다루기를 손쉽게

파이썬에는 시간을 쉽게 다루게 해주는 라이브러리는 datetime, dateutil 이 있습니다. 단순히 시간을 표시해주는 기능 외에 연산, 변환 등의 기능을 가지고 있습니다.

두 라이브러리는 간단하게 다음과 같이 설명할 수 있습니다.

  • datetime:
    • 파이썬의 표준 라이브러리로, 날짜와 시간을 처리하는 다양한 클래스와 함수를 제공합니다. 간단한 날짜 연산부터 현지 시간과 타임존을 다룰 수 있습니다.
  • dateutil:
    • 날짜 및 시간 연산을 더 편리하게 다루기 위한 서드 파티 라이브러리로, datetime 모듈의 확장 기능으로 사용됩니다. 복잡한 날짜 규칙 및 타임존을 다루기 쉽게 만들어줍니다.

두 라이브러리 모두 날짜 및 시간을 처리하는데 유용하며, dateutildatetime을 보완하여 더 풍부한 기능을 제공합니다.

저도 모든 기능을 다 알지 못하지만 다른 블로그 글보다 제 눈에 익은 정리가 찾아 쓸 때 편해서 따로 정리해보았습니다.

두 라이브러리는 공통된 기능도 존재하기 때문에 여러 기능들을 각 라이브러리에서 어떻게 쓰는지도 비교하면서 정리하였습니다.

dateutil 설치

dateutil 은 서드파티 라이브러리이기 때문에 패키지 설치가 필요합니다. python-dateutil 패키지를 아래와 같이 설치해줍니다

패키지 이름이 dateutil 이 아니라 python-dateutil 것에 유의합니다.

pip install python-dateutil

문자열 -> 데이트타입 변환

strptime() : datetime 라이브러리

from datetime import datetime

# 문자열로 된 날짜
date_string = "2022-02-20"

# 문자열을 datetime 객체로 변환
date_object = datetime.strptime(date_string, "%Y-%m-%d")

print(type(date_object))  # <class 'datetime.datetime'>
print(date_object)  # 2022-02-20 00:00:00

parse() : dateutil 라이브러리

from dateutil import parser

# 특정 포맷으로 된 날짜 문자열
date_string = "2022-02-20"

# 특정 포맷을 지정하여 문자열을 datetime 객체로 변환
date_object = parser.parse(date_string)
date = date_object.date()
print(type(date_object))  # <class 'datetime.datetime'>
print(date_object)  # 2022-02-20 00:00:00
print(type(date))  # <class 'datetime.date'>
print(date)  # 2022-02-20

여기서는 dateutil 사용이, 유연하게 문자열 변환을 할 수 있다는 것을 확인 할 수 있습니다.

datetime.strptime() 메서드는 파싱할 문자열의 형식을 정확하게 지정해야 하지만, dateutil.parser.parse 함수는 다양한 날짜 및 시간 형식을 자동으로 감지하여 처리할 수 있습니다. 이러한 유연성은 입력 문자열이 다양한 형식으로 제공되는 경우 유용합니다.

데이트타입 -> 문자열 변환

데이트타입 변수를 str 함수로 처리하면 string으로 변환 됩니다.

strftime() 메소드를 사용하면 원하는 형식의 string으로 변환 됩니다.

datetime 라이브러리

from datetime import datetime

# 날짜 및 시간 문자열
date_string = "2022-02-20 15:30:00"

# 문자열을 datetime 객체로 파싱
date = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
print(type(date))  # <class 'datetime.datetime'>
print(date)  # 2022-02-20 15:30:00

# str 변환 방법1
parsed_datetime1 = str(date)
print(type(parsed_datetime1))  # <class 'str'>
print(parsed_datetime1)  # 2022-02-20 15:30:00

# str 변환 방법2 (원하는 형식으로 변환 가능)
parsed_datetime2 = datetime.strftime(date, '%Y.%m.%d')
print(type(parsed_datetime2))  # <class 'str'>
print(parsed_datetime2)  # 2022.02.20

dateutil 라이브러리

parse() 메소드를 사용해도 반환되는 객체는 datetime이기 때문에 위와 동일하게 str() 함수와 strftime() 메소드를 사용해서 string으로 변환 할 수 있습니다.

from dateutil import parser
from datetime import datetime

# 날짜 및 시간 문자열
date_string = "2022-02-20 15:30:00"

# 문자열을 datetime 객체로 파싱
date = parser.parse(date_string)
print(type(date))  # <class 'datetime.datetime'>
print(date)  # 2022-02-20 15:30:00

# str 변환 방법1
parsed_datetime1 = str(date)
print(type(parsed_datetime1))  # <class 'str'>
print(parsed_datetime1)  # 2022-02-20 15:30:00

# str 변환 방법2 (원하는 형식으로 변환 가능)
parsed_datetime2 = datetime.strftime(date, '%Y.%m.%d')
print(type(parsed_datetime2))  # <class 'str'>
print(parsed_datetime2)  # 2022.02.20

시간 요소 가져오기

연,월,일, 요일, 날짜, 시간, 분, 초 가져오기

print(datetime.now().date())  # 날짜  2022-03-18
print(datetime.now().year)  # 년  2022
print(datetime.now().month)  # 월  3
print(datetime.now().weekday())  # 요일(숫자)  4
print(datetime.now().day)  # 날짜  18
print(datetime.now().time())  # 시간(시분초)  16:46:27.032934
print(datetime.now().hour)  # 시간  16
print(datetime.now().minute)  # 분  46
print(datetime.now().second)  # 초  27

상대적인 시간 계산

상대적인 시간 계산에도 dateutil이 더 뛰어 납니다.

timedelta() : datetime 라이브러리

datetime.timedelta 로 상대적인 시간을 처리 할 수 있습니다.

from datetime import datetime, timedelta

# 현재 날짜 및 시간 객체
current_datetime = datetime.now()

# 상대적인 시간 표현을 위해 timedelta 객체 생성
time_difference = timedelta(days=1, hours=3, minutes=30)

# 현재 시간으로부터 지난 시간 계산
result_datetime = current_datetime - time_difference

print(result_datetime)  # 2024-02-22 08:44:59.890997

relativedelta() : dateutil 라이브러리

dateutil.relativedelta는 이러한 월 간격 처리에 뛰어나며, 각 월의 길이를 고려하여 정확한 결과를 제공합니다.

from datetime import datetime
from dateutil.relativedelta import relativedelta

# 현재 날짜 및 시간 객체
current_datetime = datetime.now()

# 상대적인 시간 표현을 위해 relativedelta 객체 생성
time_difference = relativedelta(days=1, hours=3, minutes=30)

# 현재 시간으로부터 지난 시간 계산
result_datetime = current_datetime - time_difference

print(result_datetime)  # 2024-02-22 08:46:11.834557

상대적인 시간 관리에는 꼭 dateutil을 쓰자

datetime 라이브러리 사용 시 문제점

datetime.timedelta 는 일(day)을 기준으로 간격을 처리하므로 월 간격을 정확하게 처리하기 어려울 수 있습니다. 월은 길이가 다르기 때문에 상대적인 간격을 표현할 때 문제가 발생할 수 있습니다. 예를 들어, 한 달을 30일로 간주한다고 가정하면 다음과 같은 문제가 발생할 수 있습니다

from datetime import datetime, timedelta

start_date = datetime(2022, 1, 31)
one_month = timedelta(days=30)

# 한 달을 더하는 경우
end_date = start_date + one_month
print("End Date:", end_date)  # End Date: 2022-03-02 00:00:00
dateutil 라이브러리 사용으로 해결

위 코드에서는 1월 31일에 30일을 더했으나 결과는 3월 2일로 출력됩니다. 이는 timedelta가 일(day) 기준으로만 간격을 처리하기 때문에 발생하는 문제입니다. 만약 월 간격을 정확하게 처리하려면 dateutil.relativedelta를 사용하는 것이 더 적합합니다.

from dateutil.relativedelta import relativedelta
from datetime import datetime

start_date = datetime(2022, 1, 31)

# 한 달을 더하는 경우
end_date = start_date + relativedelta(months=1)
print("End Date:", end_date)  # End Date: 2022-02-28 00:00:00

타임존 관리

타임존 관리도 dateutil 라이브러리 사용이 훨씬 편합니다.

timezone, astimezone() : datetime 라이브러리

datetime 라이브러리에서는 타임존을 utc 시간대로 입력해서 변경해줘야 합니다.

  1. 뉴욕 (미국 동부): timezone(timedelta(hours=-5)) (UTC-5)
  2. 로스앤젤레스 (미국 서부): timezone(timedelta(hours=-8)) (UTC-8)
  3. 런던 (영국): timezone(timedelta(hours=0)) (UTC+0)
  4. 파리 (프랑스): timezone(timedelta(hours=1)) (UTC+1)
  5. 도쿄 (일본): timezone(timedelta(hours=9)) (UTC+9)
  6. 대한민국 (서울): timezone(timedelta(hours=9)) (UTC+9)
  7. 시드니 (호주 동부): timezone(timedelta(hours=10)) (UTC+10)
    주의: 일부 국가 및 지역은 여러 개의 시간대를 가질 수 있습니다. pytz 라이브러리를 활용하여 UTC 시간대를 확인 할 수도 있습니다.
from datetime import datetime, timedelta, timezone

# UTC(표준 시간) 타임존 생성
utc_timezone = timezone.utc

# 현재 시간을 UTC로 설정
current_time_utc = datetime.now(utc_timezone)

print("Current Time (UTC):", current_time_utc)  # Current Time (UTC): 2024-02-23 03:22:14.797708+00:00

# 뉴욕 타임존 생성
ny_timezone = timezone(timedelta(hours=-5))

# UTC 시간을 뉴욕 타임존으로 변환
current_time_ny = current_time_utc.astimezone(ny_timezone)  # Current Time (New York): 2024-02-22 22:22:14.797708-05:00

print("Current Time (New York):", current_time_ny)

tz.tzutc(), tz.gettz() : dateutil 라이브러리

dateutiltz gettz를 이용하면 특정 타임존 시간으로 쉽게 변환할 수 있습니다.

  1. “America/New_York”: 미국 동부의 타임존
  2. “Europe/London”: 영국의 타임존
  3. “Asia/Tokyo”: 일본의 타임존
  4. “Asia/Korea”: 대한민국의 타임존
  5. “Australia/Sydney”: 호주 동부의 타임존
from datetime import datetime
from dateutil import tz

# UTC(표준 시간) 타임존 생성
utc_timezone = tz.tzutc()

# 현재 시간을 UTC로 설정
current_time_utc = datetime.now(utc_timezone)

print("Current Time (UTC):", current_time_utc)  # Current Time (UTC): 2024-02-23 03:23:31.356146+00:00

# 뉴욕 타임존 생성
ny_timezone = tz.gettz("America/New_York")

# UTC 시간을 뉴욕 타임존으로 변환
current_time_ny = current_time_utc.replace(
    tzinfo=utc_timezone).astimezone(ny_timezone)

print("Current Time (New York):", current_time_ny)  # Current Time (New York): 2024-02-22 22:23:31.356146-05:00

rrule : dateutil 의 강력한 규칙 기반 날짜 생성 클래스

rruledateutil 라이브러리에서 제공하는 규칙 기반의 날짜 생성을 위한 클래스입니다. 이 클래스를 사용하면 반복적인 날짜 패턴을 정의하고 이를 기반으로 날짜를 생성할 수 있습니다.

from datetime import datetime
from dateutil.rrule import rrule, DAILY

# 시작 날짜
start_date = datetime(2022, 1, 1)

# 매일 반복하는 규칙 생성
daily_rule = rrule(DAILY, dtstart=start_date, count=5)

# 생성된 날짜 출력
for date in daily_rule:
    print(date.strftime('%Y-%m-%d'))

이 코드는 2022년 1월 1일부터 시작해서 매일을 5번 생성하여 출력합니다.

2022-01-01
2022-01-02
2022-01-03
2022-01-04
2022-01-05

반복적인 주기를 만들 수도 있습니다.

byweekdy 인자에 화요일 (TU) 를 입력하여 매주 화요일만 5번 출력하도록 해보았습니다.

from datetime import datetime
from dateutil.rrule import rrule, DAILY, TU

# 시작 날짜
start_date = datetime(2024, 2, 1)

# 매주 화요일만 반복하는 규칙 생성 (최대 5번)
weekly_rule = rrule(DAILY, dtstart=start_date, byweekday=(TU,), count=5)

# 생성된 날짜 출력
for date in weekly_rule:
    print(date.strftime('%Y-%m-%d'))
2024-02-06
2024-02-13
2024-02-20
2024-02-27
2024-03-05

rrule 파라미터

다양한 파라미터를 사용하여 규칙을 지정할 수 있습니다\

freq : 반복 주기를 나타내는 파라미터로, SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY 등이 가능합니다.

dtstart: 반복이 시작하는 날짜와 시간을 나타냅니다.

interval: 주기적으로 반복되는 간격을 나타냅니다.

count: 생성할 날짜의 최대 수를 나타냅니다.

until: 반복이 끝나는 날짜와 시간을 나타냅니다.

bysetpos: 특정 주기만 선택하는데 사용되며, 음수로 지정하면 역순으로 선택됩니다.

byweekday: 반복이 일어나는 특정 요일을 나타내는 파라미터로, MO, TU, WE, TH, FR, SA, SU 등이 가능합니다.

bymonthday: 반복이 일어나는 특정 월 중 몇 번째 날짜인지를 나타내는 파라미터입니다.

byyearday: 반복이 일어나는 특정 해 중 몇 번째 날짜인지를 나타내는 파라미터입니다.

bymonth: 반복이 일어나는 특정 월을 나타내는 파라미터로, 1월부터 12월까지의 값을 사용합니다.

byeaster: 이스터 주일을 기준으로 하는 날짜를 나타내는 파라미터입니다.

참고하면 좋은 글

https://docs.python.org/3/library/datetime.html

dateutil – powerful extensions to datetime — dateutil 2.8.2 documentation

Leave a Comment

목차