📋 목차
파이썬에서 현재 날짜와 시간을 구하려면 datetime 라이브러리의 now()나 today()를 쓰면 되는데, 막상 실무에서 쓰다 보면 포맷 변환이나 타임존 문제에서 꼭 한 번은 막히거든요.
저도 처음 파이썬 배울 때 datetime.now()로 시간 찍는 건 5분 만에 했는데, 그 뒤로 진짜 고생했어요. 로그 파일에 찍힌 시간이 UTC인 걸 모르고 한참 디버깅한 적도 있고, strftime이랑 strptime 헷갈려서 f 하나 빼먹고 에러 잡느라 야근한 적도 있거든요. 심지어 서버 배포하고 나서 시간이 9시간 밀려 있는 걸 3일째 되서야 발견한 적도 있습니다.
그래서 오늘은 제가 실제로 코드 짜면서 겪었던 삽질들을 기반으로, datetime 라이브러리의 핵심 기능만 콕 집어서 정리해볼게요. 초보자도 바로 복사해서 쓸 수 있도록 실전 코드 위주로 갑니다.
datetime.now()와 today()의 진짜 차이
파이썬에서 현재 시간을 가져오는 방법은 크게 두 가지예요. datetime.datetime.now()와 datetime.datetime.today()인데, 겉보기엔 완전히 똑같은 결과를 내거든요. 실제로 인자 없이 호출하면 둘 다 로컬 시스템 시간을 반환합니다.
근데 결정적인 차이가 하나 있어요. now()는 tz라는 타임존 인자를 받을 수 있고, today()는 못 받습니다. 이게 뭐가 중요하냐면, 나중에 서버 환경에서 UTC 시간이나 한국 시간을 명시적으로 지정해야 할 때 now()만 쓸 수 있다는 뜻이에요.
코드로 보면 이렇습니다.
from datetime import datetime
print(datetime.now()) # 2026-05-20 14:30:22.123456
print(datetime.today()) # 2026-05-20 14:30:22.123456
# 여기까진 동일
from datetime import timezone
print(datetime.now(timezone.utc)) # UTC 시간 명시 가능
# today()로는 이게 안 됨
저는 처음에 그냥 today() 쓰다가, AWS 서버에 올린 크롤러의 로그 시간이 전부 9시간 빠르게 찍혀 있어서 한참 헤맸어요. 그때부터 무조건 now()에 타임존을 명시하는 습관을 들였거든요. 로컬에서 테스트할 땐 괜찮은데, 배포 환경이 달라지면 today()는 위험합니다.
그리고 한 가지 더. Python 3.12부터 datetime.utcnow()가 deprecated 처리됐어요. 공식 문서에서도 datetime.now(timezone.utc)를 쓰라고 권장하고 있으니, utcnow() 쓰고 계신 분들은 바꾸시는 게 좋습니다.
날짜만 깔끔하게 뽑는 법
시간 정보 필요 없이 오늘 날짜만 필요한 경우가 꽤 많잖아요. 파일명에 날짜 붙이거나, DB에 날짜 컬럼 넣을 때. 이럴 땐 datetime.date 클래스를 따로 쓰는 게 훨씬 깔끔합니다.
from datetime import date, datetime
# 방법 1: date.today()
today = date.today()
print(today) # 2026-05-20
print(today.year) # 2026
print(today.month) # 5
print(today.day) # 20
# 방법 2: datetime.now().date()
today2 = datetime.now().date()
print(today2) # 2026-05-20
date.today()로 받으면 타입이 datetime.date이고, datetime.now()로 받으면 datetime.datetime이에요. date 객체는 시간 정보가 아예 없어서 hour, minute 같은 속성에 접근하면 에러가 납니다. 반대로 datetime 객체에서 .date() 메서드를 호출하면 date 객체로 변환할 수 있고요.
개인적으로 로그 파일명 만들 때 이런 패턴을 자주 씁니다.
filename = f”log_{date.today()}.txt”
# log_2026-05-20.txt
요일 정보가 필요하면 weekday() 메서드를 쓰면 되는데, 0이 월요일이고 6이 일요일이에요. isoweekday()를 쓰면 1(월요일)~7(일요일)로 반환하고요. 이거 처음에 진짜 헷갈렸는데, 저는 그냥 isoweekday() 쓰고 1 빼는 걸로 통일했어요.
💡 꿀팁
year, month, day 속성은 정수형이라 바로 연산이 가능해요. 예를 들어 today.year – 1하면 작년 연도가 나오는데, 월이나 일은 이렇게 빼면 1월에서 0월이 되니까 반드시 timedelta를 써야 합니다. 초보 때 month – 1 해서 0월 만든 경험이 있어서요.
strftime 포맷 코드, 자주 쓰는 것만 정리
strftime은 datetime 객체를 원하는 형식의 문자열로 바꿔주는 메서드예요. 이름이 “string format time”의 줄임인데, 포맷 코드를 외우는 게 은근 귀찮거든요. 저도 매번 검색하다가 결국 자주 쓰는 것만 따로 정리해놨습니다.
| 포맷 코드 | 의미 | 출력 예시 |
|---|---|---|
| %Y | 4자리 연도 | 2026 |
| %m | 월 (01~12) | 05 |
| %d | 일 (01~31) | 20 |
| %H | 시 (00~23, 24시간) | 14 |
| %M | 분 (00~59) | 30 |
| %S | 초 (00~59) | 45 |
| %A | 요일 (영문 전체) | Wednesday |
| %I | 시 (01~12, 12시간) | 02 |
| %p | AM/PM | PM |
실전에서 가장 많이 쓰는 조합은 이 세 가지예요.
from datetime import datetime
now = datetime.now()
# 패턴 1: 날짜만
print(now.strftime(“%Y-%m-%d”)) # 2026-05-20
# 패턴 2: 날짜 + 시간
print(now.strftime(“%Y-%m-%d %H:%M:%S”)) # 2026-05-20 14:30:45
# 패턴 3: 한국식 표기
print(now.strftime(“%Y년 %m월 %d일”)) # 2026년 05월 20일
여기서 진짜 자주 실수하는 게 대문자 M과 소문자 m이에요. %M은 “분”이고 %m은 “월”입니다. 이거 반대로 쓰면 에러는 안 나는데 값이 이상하게 나와서, 처음에 뭐가 잘못인지 찾기가 어렵거든요. 저는 한번 이것 때문에 크롤링 데이터 날짜가 전부 꼬인 적이 있어요. 2만 건 넘는 데이터를 다시 정리했습니다.
%H도 마찬가지예요. 대문자 H는 24시간제, 소문자 아닌 %I(대문자 아이)가 12시간제입니다. 소문자 h는 아예 없어요. 이런 디테일 때문에 공식 문서의 포맷 코드표를 한 번은 쭉 읽어보시는 걸 추천합니다.
문자열을 날짜로 바꾸는 strptime 실전 활용
strftime이 datetime을 문자열로 바꾸는 거라면, strptime은 그 반대예요. 문자열을 datetime 객체로 파싱해줍니다. “string parse time”의 줄임이라고 생각하면 외우기 쉬워요.
언제 쓰냐면, 웹 크롤링 하거나 CSV 파일 읽을 때 날짜가 문자열로 들어오는 경우가 거의 대부분이거든요. 이걸 datetime 객체로 변환해야 날짜 비교나 계산이 가능합니다.
from datetime import datetime
# 기본 변환
date_str = “2026-05-20 14:30:00”
dt = datetime.strptime(date_str, “%Y-%m-%d %H:%M:%S”)
print(dt) # 2026-05-20 14:30:00
print(type(dt)) # <class ‘datetime.datetime’>
# 한국식 날짜 문자열 변환
kor_str = “2026년 05월 20일”
dt2 = datetime.strptime(kor_str, “%Y년 %m월 %d일”)
print(dt2) # 2026-05-20 00:00:00
핵심은 두 번째 인자인 포맷 문자열이 원본 문자열의 형식과 정확히 일치해야 한다는 거예요. 공백 하나, 하이픈 하나라도 다르면 ValueError가 납니다.
⚠️ 주의
strptime에서 가장 흔한 에러가 “time data does not match format”인데, 원인의 80%는 포맷 문자열의 구분자 불일치예요. 원본이 “2026/05/20″인데 포맷을 “%Y-%m-%d”로 쓰면 당연히 터집니다. 원본 문자열을 먼저 print로 확인하는 습관이 중요해요.
실무에서 까다로운 게 날짜 형식이 데이터마다 제각각이라는 거예요. 어떤 건 “20260520”이고 어떤 건 “May 20, 2026″이고. 이럴 때 하나하나 포맷 맞추는 게 귀찮으면 dateutil이라는 서드파티 라이브러리의 parser.parse()를 쓰는 방법도 있어요. 자동으로 형식을 추론해줍니다. 다만 속도가 느리고 가끔 잘못 파싱하니까, 형식이 확정된 데이터라면 strptime이 낫습니다.
timedelta로 날짜 계산하기
날짜에서 며칠을 더하거나 빼야 할 때 timedelta를 씁니다. 이게 없었으면 매달 일수가 다른 걸 직접 계산했어야 하는데, 파이썬이 알아서 해줘요.
from datetime import datetime, timedelta
now = datetime.now()
# 7일 후
after_7days = now + timedelta(days=7)
print(after_7days.strftime(“%Y-%m-%d”))
# 30일 전
before_30days = now – timedelta(days=30)
print(before_30days.strftime(“%Y-%m-%d”))
# 3시간 30분 후
later = now + timedelta(hours=3, minutes=30)
print(later.strftime(“%H:%M:%S”))
# 두 날짜 간 차이 계산
d1 = datetime(2026, 1, 1)
d2 = datetime(2026, 5, 20)
diff = d2 – d1
print(diff.days) # 139
timedelta에는 days, seconds, microseconds, milliseconds, minutes, hours, weeks를 인자로 넣을 수 있는데, 내부적으로는 days, seconds, microseconds 세 가지만 저장돼요. 나머지는 전부 이 세 단위로 변환됩니다.
한 가지 아쉬운 점은 timedelta에 months나 years 인자가 없다는 거예요. “정확히 한 달 후”를 구하려면 timedelta만으로는 안 됩니다. 한 달이 28일인지 30일인지 31일인지가 달마다 다르니까요. 이럴 땐 dateutil 라이브러리의 relativedelta를 쓰거나, 직접 월을 더한 뒤 말일 처리를 해줘야 해요.
# pip install python-dateutil
from dateutil.relativedelta import relativedelta
now = datetime.now()
one_month_later = now + relativedelta(months=1)
one_year_ago = now – relativedelta(years=1)
print(one_month_later) # 정확히 한 달 후
print(one_year_ago) # 정확히 1년 전
저는 예전에 timedelta(days=30)으로 “한 달 전” 데이터를 필터링했다가, 2월 달에 데이터가 2일치나 빠져 있는 걸 나중에 발견했어요. 그 뒤로 월 단위 계산은 무조건 relativedelta 쓰고 있습니다.
한국 시간(KST) 제대로 설정하는 방법
이 부분이 진짜 중요한데, 의외로 가볍게 넘기는 분이 많더라고요. 로컬 PC에서 개발할 때는 시스템 시간이 한국 시간이니까 문제가 없어요. 근데 AWS, GCP 같은 클라우드 서버는 기본 시간대가 UTC(협정세계시)인 경우가 대부분입니다. UTC는 한국 시간보다 9시간 느려요.
예전에는 pytz 라이브러리를 많이 썼는데, Python 3.9부터 표준 라이브러리에 zoneinfo 모듈이 추가됐어요. 이제 별도 설치 없이 타임존을 처리할 수 있습니다.
# Python 3.9+ 권장 방식 (zoneinfo)
from datetime import datetime
from zoneinfo import ZoneInfo
# 한국 시간으로 현재 시각 가져오기
kst_now = datetime.now(ZoneInfo(“Asia/Seoul”))
print(kst_now) # 2026-05-20 14:30:45+09:00
# UTC 시간
utc_now = datetime.now(ZoneInfo(“UTC”))
print(utc_now) # 2026-05-20 05:30:45+00:00
# UTC → KST 변환
utc_time = datetime.now(ZoneInfo(“UTC”))
kst_time = utc_time.astimezone(ZoneInfo(“Asia/Seoul”))
print(kst_time) # +09:00이 붙은 한국 시간
📊 실제 데이터
Python 공식 문서에 따르면, Python 3.12부터 datetime.utcnow()와 datetime.utcfromtimestamp()가 공식적으로 deprecated됐어요. 대안으로 datetime.now(datetime.timezone.utc) 또는 datetime.now(ZoneInfo(“UTC”))를 쓰라고 명시하고 있습니다. 기존 코드에 utcnow()가 있다면 점진적으로 교체하는 게 좋습니다.
혹시 Python 3.8 이하를 쓰고 계시면 zoneinfo가 없으니 pytz를 써야 합니다. Windows에서 zoneinfo 쓸 때 tzdata 패키지가 없다는 에러가 나면 pip install tzdata로 설치하면 돼요.
# Python 3.8 이하 또는 pytz 사용 시
import pytz
from datetime import datetime
kst = pytz.timezone(“Asia/Seoul”)
kst_now = datetime.now(kst)
print(kst_now)
pytz를 쓸 때 주의할 점이 있는데, datetime 생성자에 직접 tzinfo를 넣으면 안 되고 반드시 localize() 메서드를 써야 해요. 이게 pytz의 고질적인 함정이거든요. zoneinfo는 그런 문제가 없어서 가능하면 3.9 이상으로 올리시는 걸 권합니다.
💬 직접 써본 경험
실제로 운영 중인 Django 프로젝트에서 pytz를 zoneinfo로 마이그레이션한 적이 있는데, settings.py의 USE_TZ = True 설정만 제대로 돼 있으면 생각보다 어렵지 않았어요. 다만 DB에 이미 naive datetime으로 저장된 데이터가 있으면 그 부분은 별도 마이그레이션이 필요합니다. 이거 모르고 바로 바꿨다가 기존 예약 시간이 9시간씩 밀리는 사고가 나서, 급하게 롤백했던 기억이 나네요.
자주 묻는 질문
Q. datetime.now()와 datetime.today()는 정말 같은 건가요?
인자 없이 호출하면 동일한 결과를 반환해요. 차이는 now()만 타임존(tz) 인자를 받을 수 있다는 점이에요. 서버 환경을 고려하면 now()를 쓰는 게 확장성 면에서 유리합니다.
Q. strftime과 strptime, 어떤 게 “변환”이고 어떤 게 “포맷”인가요?
strftime은 datetime → 문자열(format), strptime은 문자열 → datetime(parse)이에요. f는 format의 f, p는 parse의 p로 기억하면 안 헷갈립니다.
Q. timedelta로 정확히 한 달을 더할 수 있나요?
timedelta에는 months 인자가 없어서 직접은 안 돼요. python-dateutil 라이브러리의 relativedelta(months=1)을 쓰면 정확히 한 달 뒤 날짜를 구할 수 있습니다.
Q. Python 3.12에서 utcnow()를 쓰면 어떻게 되나요?
DeprecationWarning이 발생합니다. 당장 에러가 나진 않지만, 향후 버전에서 제거될 수 있어요. datetime.now(timezone.utc) 또는 datetime.now(ZoneInfo(“UTC”))로 바꾸는 게 좋습니다.
Q. Windows에서 zoneinfo 사용 시 에러가 나는 이유는?
Windows는 IANA 타임존 데이터베이스가 기본 내장이 아니라서 그래요. pip install tzdata 명령으로 tzdata 패키지를 설치하면 해결됩니다. macOS와 Linux는 시스템에 포함돼 있어서 별도 설치가 필요 없고요.
본 포스팅은 개인 경험과 공개 자료를 바탕으로 작성되었으며, 전문적인 의료·법률·재무 조언을 대체하지 않습니다. 정확한 정보는 해당 분야 전문가 또는 공식 기관에 확인하시기 바랍니다.
파이썬 datetime 라이브러리는 now(), strftime/strptime, timedelta, 그리고 zoneinfo 이 네 가지만 확실히 잡으면 실무에서 날짜 관련 작업의 90%는 처리할 수 있어요. 특히 서버 배포를 앞두고 있다면 타임존 설정은 반드시 미리 챙기시고, Python 3.9 이상이라면 pytz 대신 zoneinfo를 쓰는 게 앞으로의 유지보수에 훨씬 유리합니다.
datetime 관련해서 궁금한 점이나 실무에서 겪은 에러가 있다면 댓글로 남겨주세요. 비슷한 삽질을 줄이는 데 도움이 될 수 있으니까요. 도움이 됐다면 공유도 부탁드려요!