파이썬 datetime 날짜 시간 완벽 가이드

프로그램에서 현재 시간을 기록하거나 특정 날짜를 계산해야 하는데 막막하신가요? 크롤링 데이터에 타임스탬프를 추가하거나, 로그에 시간을 기록하거나, 일정을 관리하는 모든 상황에서 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로 날짜를 계산하는 것이 핵심입니다. 크롤링 데이터에 타임스탬프 추가, 로그 기록, 일정 계산 등 실무에서 즉시 활용 가능한 예제들을 참고해보세요.

시간대 처리, 요일 계산, 월 단위 계산까지 마스터하면 어떤 날짜 시간 작업도 자유롭게 다룰 수 있습니다. 이 가이드의 코드를 프로젝트에 바로 적용해보세요.


참고 자료

댓글 남기기