프로그램에서 현재 시간을 기록하거나 특정 날짜를 계산해야 하는데 막막하신가요? 크롤링 데이터에 타임스탬프를 추가하거나, 로그에 시간을 기록하거나, 일정을 관리하는 모든 상황에서 datetime은 필수입니다. 이 글에서는 기초부터 실전 활용까지 완벽하게 알려드립니다.
datetime이 필요한 이유
웹 크롤링 데이터 수집 시간 기록, 로그 파일 타임스탬프, 데이터베이스 날짜 저장, 일정 계산, 시간대 변환 등 프로그래밍에서 시간 처리는 필수입니다. datetime 모듈을 마스터하면 모든 시간 관련 작업을 자유자재로 다룰 수 있습니다.
datetime 모듈 기본 구조
핵심 클래스 이해하기
from datetime import datetime, date, time, timedelta
# datetime: 날짜 + 시간
now = datetime.now()
print(now) # 2025-10-07 14:30:25.123456
# date: 날짜만
today = date.today()
print(today) # 2025-10-07
# time: 시간만
current_time = datetime.now().time()
print(current_time) # 14:30:25.123456
# timedelta: 시간 간격
delta = timedelta(days=7)
print(delta) # 7 days, 0:00:00
구조 이해: datetime은 날짜와 시간을 모두 포함하고, date는 날짜만, time은 시간만 다룹니다.
현재 날짜 시간 구하기
현재 날짜와 시간
from datetime import datetime
# 현재 날짜 + 시간 (가장 많이 사용)
now = datetime.now()
print(f"현재: {now}")
print(f"연도: {now.year}")
print(f"월: {now.month}")
print(f"일: {now.day}")
print(f"시: {now.hour}")
print(f"분: {now.minute}")
print(f"초: {now.second}")
print(f"마이크로초: {now.microsecond}")
# 출력 예시:
# 현재: 2025-10-07 14:30:25.123456
# 연도: 2025
# 월: 10
# 일: 7
# 시: 14
# 분: 30
# 초: 25
# 마이크로초: 123456
실무 활용: 크롤링 데이터 수집 시간을 기록할 때 가장 많이 사용합니다.
오늘 날짜만
from datetime import date
# 오늘 날짜
today = date.today()
print(f"오늘: {today}") # 2025-10-07
print(f"연도: {today.year}")
print(f"월: {today.month}")
print(f"일: {today.day}")
print(f"요일: {today.weekday()}") # 0(월)~6(일)
날짜 계산: 시간 정보가 필요 없을 때 date를 사용하면 더 가볍습니다.
현재 시간만
from datetime import datetime
current_time = datetime.now().time()
print(f"현재 시간: {current_time}") # 14:30:25.123456
print(f"시: {current_time.hour}")
print(f"분: {current_time.minute}")
print(f"초: {current_time.second}")
시간만 필요: 날짜와 무관하게 시간만 다룰 때 사용합니다.
날짜 시간 포맷팅
strftime() – 날짜를 문자열로
from datetime import datetime
now = datetime.now()
# 다양한 포맷
print(now.strftime("%Y-%m-%d")) # 2025-10-07
print(now.strftime("%Y년 %m월 %d일")) # 2025년 10월 07일
print(now.strftime("%H:%M:%S")) # 14:30:25
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2025-10-07 14:30:25
# 요일 포함
print(now.strftime("%Y-%m-%d (%A)")) # 2025-10-07 (Tuesday)
print(now.strftime("%Y-%m-%d (%a)")) # 2025-10-07 (Tue)
# 12시간 형식
print(now.strftime("%Y-%m-%d %I:%M:%S %p")) # 2025-10-07 02:30:25 PM
# 파일명용 타임스탬프
print(now.strftime("%Y%m%d_%H%M%S")) # 20251007_143025
주요 포맷 코드:
%Y: 4자리 연도 (2025)%m: 2자리 월 (01-12)%d: 2자리 일 (01-31)%H: 24시간 형식 시 (00-23)%I: 12시간 형식 시 (01-12)%M: 분 (00-59)%S: 초 (00-59)%p: AM/PM%A: 요일 전체 (Monday)%a: 요일 약자 (Mon)
실전 활용 예제
from datetime import datetime
# 로그 파일명 생성
now = datetime.now()
log_filename = f"log_{now.strftime('%Y%m%d_%H%M%S')}.txt"
print(log_filename) # log_20251007_143025.txt
# 데이터베이스용 포맷
db_timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
print(db_timestamp) # 2025-10-07 14:30:25
# 사용자 친화적 포맷
user_friendly = now.strftime("%Y년 %m월 %d일 %p %I시 %M분")
print(user_friendly) # 2025년 10월 07일 PM 02시 30분
파일명 생성: 크롤링 결과를 날짜별로 저장할 때 유용합니다.
문자열을 날짜로 변환
strptime() – 문자열 파싱
from datetime import datetime
# 문자열을 datetime 객체로 변환
date_str = "2025-10-07 14:30:25"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(dt) # 2025-10-07 14:30:25
print(type(dt)) # <class 'datetime.datetime'>
# 다양한 형식 파싱
date_str2 = "2025년 10월 07일"
dt2 = datetime.strptime(date_str2, "%Y년 %m월 %d일")
print(dt2) # 2025-10-07 00:00:00
date_str3 = "07/10/2025 14:30"
dt3 = datetime.strptime(date_str3, "%d/%m/%Y %H:%M")
print(dt3) # 2025-10-07 14:30:00
웹 크롤링: 웹사이트에서 텍스트로 된 날짜를 수집해 datetime 객체로 변환할 때 필수입니다.
예외 처리
from datetime import datetime
def parse_date_safely(date_str, format_str):
try:
return datetime.strptime(date_str, format_str)
except ValueError as e:
print(f"❌ 날짜 형식 오류: {e}")
return None
# 잘못된 형식
result = parse_date_safely("2025-13-45", "%Y-%m-%d") # None
if result:
print(result)
else:
print("날짜 파싱 실패")
안전성: 사용자 입력이나 크롤링 데이터는 항상 예외 처리를 해야 합니다.
날짜 계산하기
timedelta로 날짜 더하기/빼기
from datetime import datetime, timedelta
now = datetime.now()
print(f"현재: {now.strftime('%Y-%m-%d %H:%M:%S')}")
# 7일 후
after_7days = now + timedelta(days=7)
print(f"7일 후: {after_7days.strftime('%Y-%m-%d')}")
# 30일 전
before_30days = now - timedelta(days=30)
print(f"30일 전: {before_30days.strftime('%Y-%m-%d')}")
# 3시간 후
after_3hours = now + timedelta(hours=3)
print(f"3시간 후: {after_3hours.strftime('%H:%M:%S')}")
# 복합 계산
complex_delta = now + timedelta(days=7, hours=3, minutes=30)
print(f"7일 3시간 30분 후: {complex_delta}")
실무 예시: 크롤링 스케줄 계산, 쿠폰 만료일 설정, 알림 시간 계산 등에 활용합니다.
날짜 간격 계산
from datetime import datetime
start_date = datetime(2025, 1, 1)
end_date = datetime(2025, 10, 7)
# 두 날짜 간 차이
difference = end_date - start_date
print(f"경과 일수: {difference.days}일") # 279일
print(f"경과 시간: {difference.total_seconds()}초")
print(f"경과 시간: {difference.total_seconds() / 3600:.2f}시간")
# D-Day 계산
target_date = datetime(2025, 12, 31)
today = datetime.now()
dday = (target_date - today).days
print(f"D-{dday}")
이벤트 관리: 남은 날짜 계산, 프로젝트 기간 계산 등에 사용합니다.
특정 날짜 생성하기
datetime 객체 직접 생성
from datetime import datetime, date, time
# 특정 날짜 + 시간 생성
specific_datetime = datetime(2025, 12, 25, 15, 30, 45)
print(specific_datetime) # 2025-12-25 15:30:45
# 특정 날짜만
specific_date = date(2025, 12, 25)
print(specific_date) # 2025-12-25
# 특정 시간만
specific_time = time(15, 30, 45)
print(specific_time) # 15:30:45
# date와 time 결합
combined = datetime.combine(specific_date, specific_time)
print(combined) # 2025-12-25 15:30:45
일정 생성: 특정 날짜의 이벤트를 프로그래밍으로 생성할 때 사용합니다.
실전 활용 예제
크롤링 데이터에 타임스탬프 추가
from datetime import datetime
import pymysql
def save_keyword_with_timestamp(keyword, rank, source):
conn = pymysql.connect(
host='localhost',
user='root',
password='password',
database='keyword_db'
)
cursor = conn.cursor()
# 현재 시간 가져오기
collected_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
sql = "INSERT INTO keywords (keyword, rank, source, collected_at) VALUES (%s, %s, %s, %s)"
val = (keyword, rank, source, collected_at)
cursor.execute(sql, val)
conn.commit()
print(f"✅ [{collected_at}] {keyword} 저장 완료")
cursor.close()
conn.close()
# 사용 예시
save_keyword_with_timestamp("파이썬", 1, "google")
데이터 추적: 언제 수집했는지 기록해 시계열 분석이 가능합니다.
로그 파일에 타임스탬프 기록
from datetime import datetime
def write_log(message, level="INFO"):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] [{level}] {message}\\\\n"
with open("app.log", 'a', encoding='utf-8') as f:
f.write(log_entry)
print(log_entry.strip())
# 사용 예시
write_log("애플리케이션 시작")
write_log("크롤링 시작: Google Trends")
write_log("데이터베이스 연결 실패", level="ERROR")
write_log("크롤링 완료: 100개 키워드 수집")
로깅 시스템: 모든 이벤트에 정확한 시간을 기록합니다.
날짜별 파일 저장
from datetime import datetime
import os
def save_daily_crawling_data(keywords):
# 오늘 날짜로 폴더 생성
today = datetime.now().strftime("%Y%m%d")
folder_path = f"data/{today}"
os.makedirs(folder_path, exist_ok=True)
# 시간 포함 파일명
timestamp = datetime.now().strftime("%H%M%S")
filename = f"{folder_path}/keywords_{timestamp}.txt"
with open(filename, 'w', encoding='utf-8') as f:
for keyword in keywords:
f.write(f"{keyword}\\\\n")
print(f"✅ 저장 완료: {filename}")
# 사용 예시
keywords = ["파이썬", "크롤링", "데이터분석"]
save_daily_crawling_data(keywords)
# 결과: data/20251007/keywords_143025.txt
파일 관리: 날짜별로 데이터를 정리해 관리가 쉬워집니다.
주기적 크롤링 스케줄러
from datetime import datetime, time
import time as time_module
def should_crawl_now():
"""매일 오전 9시, 오후 3시, 오후 9시에 크롤링"""
now = datetime.now().time()
schedule_times = [time(9, 0), time(15, 0), time(21, 0)]
for schedule_time in schedule_times:
# 현재 시간이 스케줄 시간과 1분 이내 차이면 True
if schedule_time.hour == now.hour and abs(schedule_time.minute - now.minute) <= 1:
return True
return False
def crawling_scheduler():
last_crawl = None
while True:
now = datetime.now()
if should_crawl_now():
# 같은 시간대에 중복 실행 방지
if last_crawl != now.hour:
print(f"🔍 [{now.strftime('%Y-%m-%d %H:%M:%S')}] 크롤링 시작")
# 여기서 실제 크롤링 함수 호출
perform_crawling()
last_crawl = now.hour
time_module.sleep(60) # 1분마다 체크
def perform_crawling():
# 실제 크롤링 로직
print("크롤링 수행 중...")
# 사용: crawling_scheduler()
자동화: 특정 시간에 자동으로 크롤링을 실행합니다.
요일 다루기
요일 확인 및 계산
from datetime import datetime, timedelta
now = datetime.now()
# 요일 확인 (0=월요일, 6=일요일)
weekday = now.weekday()
weekday_names = ["월", "화", "수", "목", "금", "토", "일"]
print(f"오늘은 {weekday_names[weekday]}요일")
# 다음 월요일 찾기
days_until_monday = (7 - weekday) % 7
if days_until_monday == 0:
days_until_monday = 7
next_monday = now + timedelta(days=days_until_monday)
print(f"다음 월요일: {next_monday.strftime('%Y-%m-%d')}")
# 이번 주 월요일 찾기
days_since_monday = weekday
this_monday = now - timedelta(days=days_since_monday)
print(f"이번 주 월요일: {this_monday.strftime('%Y-%m-%d')}")
# 주말인지 확인
is_weekend = weekday >= 5 # 토요일(5) 또는 일요일(6)
print(f"주말 여부: {is_weekend}")
업무 자동화: 평일에만 작업하거나 주말에만 특정 작업을 수행할 때 사용합니다.
월 계산하기
다음 달, 이전 달 구하기
from datetime import datetime
from dateutil.relativedelta import relativedelta
now = datetime.now()
# 다음 달
next_month = now + relativedelta(months=1)
print(f"다음 달: {next_month.strftime('%Y-%m')}")
# 3개월 후
after_3months = now + relativedelta(months=3)
print(f"3개월 후: {after_3months.strftime('%Y-%m')}")
# 1년 후
next_year = now + relativedelta(years=1)
print(f"1년 후: {next_year.strftime('%Y-%m-%d')}")
# 이번 달 마지막 날
from calendar import monthrange
last_day = monthrange(now.year, now.month)[1]
last_date = datetime(now.year, now.month, last_day)
print(f"이번 달 마지막 날: {last_date.strftime('%Y-%m-%d')}")
설치 필요: pip install python-dateutil
월 단위 계산: 구독 서비스 갱신일, 월간 리포트 생성 등에 활용합니다.
시간대(Timezone) 다루기
UTC와 로컬 시간
from datetime import datetime, timezone
import pytz
# UTC 시간
utc_now = datetime.now(timezone.utc)
print(f"UTC: {utc_now}")
# 한국 시간 (KST = UTC+9)
kst = pytz.timezone('Asia/Seoul')
korea_now = datetime.now(kst)
print(f"한국: {korea_now}")
# UTC를 한국 시간으로 변환
utc_time = datetime(2025, 10, 7, 5, 30, 0, tzinfo=timezone.utc)
korea_time = utc_time.astimezone(kst)
print(f"UTC {utc_time.strftime('%H:%M')} = KST {korea_time.strftime('%H:%M')}")
# 다양한 시간대
ny_tz = pytz.timezone('America/New_York')
london_tz = pytz.timezone('Europe/London')
tokyo_tz = pytz.timezone('Asia/Tokyo')
print(f"뉴욕: {datetime.now(ny_tz).strftime('%H:%M')}")
print(f"런던: {datetime.now(london_tz).strftime('%H:%M')}")
print(f"도쿄: {datetime.now(tokyo_tz).strftime('%H:%M')}")
설치 필요: pip install pytz
글로벌 서비스: 여러 국가의 사용자를 대상으로 할 때 필수입니다.
시간 비교하기
날짜 비교 연산
from datetime import datetime
date1 = datetime(2025, 10, 7)
date2 = datetime(2025, 12, 25)
date3 = datetime(2025, 10, 7)
# 비교 연산자
print(date1 < date2) # True
print(date1 > date2) # False
print(date1 == date3) # True
print(date1 != date2) # True
# 현재 시간과 비교
now = datetime.now()
target = datetime(2025, 12, 31, 23, 59, 59)
if now < target:
remaining = (target - now).days
print(f"목표일까지 {remaining}일 남음")
else:
print("목표일이 지났습니다")
조건 분기: 특정 날짜 이전/이후에 다른 동작을 수행할 때 사용합니다.
유효 기간 체크
from datetime import datetime, timedelta
def is_valid_coupon(expiry_date_str):
"""쿠폰 유효 기간 확인"""
expiry_date = datetime.strptime(expiry_date_str, "%Y-%m-%d")
now = datetime.now()
if now <= expiry_date:
remaining = (expiry_date - now).days
print(f"✅ 유효함 (남은 기간: {remaining}일)")
return True
else:
print("❌ 만료됨")
return False
# 사용 예시
is_valid_coupon("2025-12-31") # 유효함
is_valid_coupon("2024-01-01") # 만료됨
쿠폰 시스템: 만료일 체크, 이벤트 기간 확인 등에 활용합니다.
성능 측정하기
코드 실행 시간 측정
from datetime import datetime
import time
# 방법 1: datetime 사용
start = datetime.now()
# 시간이 걸리는 작업
time.sleep(2)
result = sum(range(1000000))
end = datetime.now()
elapsed = end - start
print(f"실행 시간: {elapsed.total_seconds()}초")
# 방법 2: time 모듈 (더 정확)
import time
start_time = time.time()
# 작업 수행
time.sleep(1)
end_time = time.time()
print(f"실행 시간: {end_time - start_time:.4f}초")
성능 분석: 크롤링 소요 시간, 데이터 처리 속도 측정에 사용합니다.
크롤링 시간 추적
from datetime import datetime
def crawl_with_timing(url):
start = datetime.now()
print(f"🔍 [{start.strftime('%H:%M:%S')}] 크롤링 시작: {url}")
# 크롤링 작업 (예시)
import time
time.sleep(2) # 실제로는 requests.get() 등
end = datetime.now()
elapsed = (end - start).total_seconds()
print(f"✅ [{end.strftime('%H:%M:%S')}] 완료 (소요시간: {elapsed:.2f}초)")
return elapsed
# 여러 URL 크롤링 시간 측정
urls = ["site1.com", "site2.com", "site3.com"]
total_time = 0
for url in urls:
elapsed = crawl_with_timing(url)
total_time += elapsed
print(f"\\\\n📊 총 소요시간: {total_time:.2f}초")
모니터링: 크롤링 성능을 추적하고 최적화 포인트를 찾습니다.
자주 하는 실수와 해결법
실수 1: naive vs aware datetime
from datetime import datetime, timezone
# naive datetime (시간대 정보 없음)
naive = datetime.now()
print(f"Naive: {naive.tzinfo}") # None
# aware datetime (시간대 정보 있음)
aware = datetime.now(timezone.utc)
print(f"Aware: {aware.tzinfo}") # UTC
# 비교 시 오류
try:
result = naive < aware # TypeError!
except TypeError as e:
print(f"❌ 오류: {e}")
# 해결: 둘 다 aware로 변환
naive_aware = naive.replace(tzinfo=timezone.utc)
result = naive_aware < aware
print(f"✅ 비교 성공: {result}")
주의: 시간대가 중요한 경우 항상 aware datetime을 사용하세요.
실수 2: 문자열 포맷 불일치
from datetime import datetime
date_str = "2025-10-07"
# 잘못된 포맷
try:
dt = datetime.strptime(date_str, "%Y/%m/%d") # 포맷 불일치!
except ValueError as e:
print(f"❌ 오류: {e}")
# 올바른 포맷
dt = datetime.strptime(date_str, "%Y-%m-%d")
print(f"✅ 성공: {dt}")
디버깅 팁: 포맷 문자열이 실제 데이터와 정확히 일치하는지 확인하세요.
마치며
파이썬 datetime 모듈은 datetime.now()로 현재 시간을 가져오고, strftime()으로 포맷팅하며, timedelta로 날짜를 계산하는 것이 핵심입니다. 크롤링 데이터에 타임스탬프 추가, 로그 기록, 일정 계산 등 실무에서 즉시 활용 가능한 예제들을 참고해보세요.
시간대 처리, 요일 계산, 월 단위 계산까지 마스터하면 어떤 날짜 시간 작업도 자유롭게 다룰 수 있습니다. 이 가이드의 코드를 프로젝트에 바로 적용해보세요.
참고 자료
- Python 공식 문서 – datetime: https://docs.python.org/3/library/datetime.html
- strftime 포맷 코드: https://strftime.org/
- pytz 타임존 목록: https://gist.github.com/heyalexej/8bf688fd67d7199be4a1682b3eec7568