23. 날짜와 시간

🎯 이 장의 목표
  • date·datetime으로 날짜와 시간을 다룬다.
  • timedelta로 시간 간격을 계산한다.
  • 날짜와 문자열을 서로 변환한다(strftime·strptime).
  • 타임존을 이해하고, 코드의 실행 시간을 측정한다.

먼저: 왜 전용 도구가 필요한가

"3일 뒤는 며칠일까?", "두 날짜 사이는 며칠 차이일까?", "이 코드는 몇 초 걸렸을까?" — 날짜·시간 계산은 의외로 까다롭습니다. 월마다 일수가 다르고, 윤년이 있고, 시간대가 다릅니다. 이를 직접 계산하면 버그투성이가 됩니다.

Python의 datetime 모듈은 이 모든 복잡함을 처리해줍니다. 표준 라이브러리라 설치 없이 바로 씁니다.

PYTHON
from datetime import date, timedelta

today = date(2025, 12, 31)
next_week = today + timedelta(days=7)
print(next_week)        # 2026-01-07   (월·연도 넘어가도 정확!)

12월 31일에 7일을 더하면 알아서 1월 7일로 넘어갑니다. 윤년·월말 계산을 우리가 신경 쓸 필요가 없습니다.

📌 핵심
핵심: 날짜·시간은 직접 계산하지 말고 datetime 모듈에 맡긴다. 윤년·월말·시간대 같은 복잡함을 정확히 처리해준다.

date: 날짜

date는 연·월·일만 다룹니다(시간 없음).

PYTHON
from datetime import date

d = date(2025, 12, 31)
print(d)                # 2025-12-31
print(d.year, d.month, d.day)   # 2025 12 31
print(d.weekday())      # 2   (요일: 월=0, 화=1, 수=2 ... 일=6)

today = date.today()    # 오늘 날짜
print(today)

weekday()는 요일을 숫자로 줍니다(월요일이 0). 수요일이면 2입니다.

datetime: 날짜 + 시간

datetime은 날짜에 시·분·초까지 더합니다.

PYTHON
from datetime import datetime

dt = datetime(2025, 12, 31, 14, 30, 0)   # 연,월,일,시,분,초
print(dt)               # 2025-12-31 14:30:00
print(dt.hour, dt.minute)   # 14 30

now = datetime.now()    # 현재 날짜+시간
print(now)              # 예: 2025-12-31 14:35:22.123456
클래스다루는 것
date날짜만 (연월일)date(2025, 12, 31)
datetime날짜 + 시간datetime(2025, 12, 31, 14, 30)
time시간만 (시분초)time(14, 30)
timedelta시간 간격timedelta(days=7)

⭐ timedelta: 시간 간격 계산

timedelta는 "기간"을 나타냅니다. 날짜에 더하거나 빼서 미래·과거를 구하고, 두 날짜를 빼서 차이를 구합니다.

PYTHON
from datetime import date, datetime, timedelta

today = date(2025, 12, 31)

# 더하기/빼기
print(today + timedelta(days=7))     # 2026-01-07   (일주일 후)
print(today - timedelta(days=1))     # 2025-12-30   (어제)
print(today + timedelta(weeks=2))    # 2026-01-14   (2주 후)

# 날짜 차이 (빼면 timedelta가 나옴)
diff = date(2026, 1, 15) - date(2025, 12, 31)
print(diff.days)        # 15   (15일 차이)

timedeltadays·weeks·hours·minutes·seconds 등으로 만듭니다.

PYTHON
from datetime import datetime, timedelta

meeting = datetime(2025, 12, 31, 14, 0)
reminder = meeting - timedelta(minutes=30)   # 30분 전 알림
print(reminder)         # 2025-12-31 13:30:00
📌 핵심
핵심: 날짜 ± timedelta = 다른 날짜. 날짜 − 날짜 = timedelta. 이 두 규칙으로 미래·과거·차이를 모두 계산한다.
flowchart LR
    D1["날짜 A"]:::data -->|"+ timedelta"| D2["미래 날짜"]:::result
    D1 -->|"- timedelta"| D3["과거 날짜"]:::result
    D1 -.- Minus["A - B"]:::proc -.->|"= timedelta"| Diff["간격(.days)"]:::result

    classDef data fill:#a8dadc,stroke:#457b9d,color:#1d3557
    classDef proc fill:#7fd8d8,stroke:#2a9d8f,color:#14532d
    classDef result fill:#b8e6c1,stroke:#34a853,color:#14532d

날짜 ↔ 문자열 변환

날짜를 화면에 표시하거나, 사용자 입력·파일의 날짜 문자열을 읽을 때 변환이 필요합니다.

strftime: 날짜 → 문자열 (포맷)

strftime("string format time")은 날짜를 원하는 형식의 문자열로 만듭니다. % 기호로 각 부분을 지정합니다.

PYTHON
from datetime import datetime

dt = datetime(2025, 12, 31, 14, 30, 45)
print(dt.strftime("%Y-%m-%d"))          # 2025-12-31
print(dt.strftime("%H:%M:%S"))          # 14:30:45
print(dt.strftime("%Y년 %m월 %d일"))     # 2025년 12월 31일
print(dt.strftime("%Y-%m-%d %H:%M"))    # 2025-12-31 14:30
기호의미
%Y연도 4자리2025
%m월 (01~12)12
%d일 (01~31)31
%H시 (00~23)14
%M30
%S45
%A요일 이름Wednesday
💡 팁
% 형식은 22장 로깅의 datefmt와 똑같습니다. 한 번 익히면 여러 곳에서 씁니다.

strptime: 문자열 → 날짜 (파싱)

strptime("string parse time")은 반대로, 날짜 문자열을 datetime 객체로 바꿉니다. 어떤 형식인지 알려줘야 합니다.

PYTHON
from datetime import datetime

s = "2025-12-31 14:30"
dt = datetime.strptime(s, "%Y-%m-%d %H:%M")    # 형식을 명시
print(dt)               # 2025-12-31 14:30:00
print(dt.year)          # 2025   (이제 계산 가능!)
print(dt + timedelta(days=1))   # 다음 날
⚠️ 흔한 실수
흔한 함정 — 형식 불일치: strptime의 형식이 실제 문자열과 다르면 ValueError가 납니다. "2025/12/31""%Y-%m-%d"(하이픈)로 파싱하려 하면 실패합니다. 구분자까지 정확히 맞춰야 합니다.
💡 팁
f → 만들기, p → 파싱으로 외우세요. strftime은 포맷(만들기), strptime은 파싱(읽기)입니다.

타임존 다루기

같은 순간이라도 지역마다 시각이 다릅니다(서울 21시 = 런던 12시). 시간대를 명시하지 않은 datetime을 "naive"(순진한), 명시한 것을 "aware"(인식하는)라고 합니다.

Python 3.9부터 표준 zoneinfo로 세계 시간대를 다룹니다.

PYTHON
from datetime import datetime
from zoneinfo import ZoneInfo

# UTC(세계 표준시) 기준 시각
utc = datetime(2025, 12, 31, 12, 0, tzinfo=ZoneInfo("UTC"))
print(utc)              # 2025-12-31 12:00:00+00:00

# 서울 시각으로 변환
seoul = utc.astimezone(ZoneInfo("Asia/Seoul"))
print(seoul)            # 2025-12-31 21:00:00+09:00   (+9시간)

# 뉴욕 시각으로 변환
ny = utc.astimezone(ZoneInfo("America/New_York"))
print(ny)               # 2025-12-31 07:00:00-05:00   (-5시간)

astimezone은 "같은 순간"을 다른 시간대의 표시로 바꿉니다(시간이 달라지는 게 아니라 표현이 달라짐).

💡 팁
시간대 이름은 "Asia/Seoul", "America/New_York" 같은 IANA 표준 이름을 씁니다. 서버·로그를 다룰 때는 UTC로 저장하고 표시할 때만 지역 시간으로 변환하는 것이 정석입니다. 시간대를 섞으면 버그의 온상이 됩니다.
📎 UTC(Coordinated Universal Time)는 세계 표준시로, 시간대 계산의 기준점입니다. "협정 세계시"라고도 합니다.

⭐ 코드 실행 시간 측정

"이 함수가 얼마나 걸리나?"를 잴 때는 datetime이 아니라 time.perf_counter()를 씁니다. 가장 정밀한 시간 측정용 함수입니다.

PYTHON
import time

start = time.perf_counter()
total = sum(range(1_000_000))       # 측정할 작업
elapsed = time.perf_counter() - start

print(f"걸린 시간: {elapsed:.4f}초")   # 걸린 시간: 0.0xxx초

perf_counter()는 어떤 절대 시각이 아니라 "흘러간 시간을 재는 스톱워치"입니다. 시작과 끝에서 호출해 차이를 구하면 경과 시간이 나옵니다.

💡 팁
중급편 17장의 데코레이터를 기억하나요? @measure 데코레이터가 바로 이 perf_counter로 함수 실행 시간을 쟀습니다. 데코레이터 + 시간 측정을 결합하면 어떤 함수든 시간을 잴 수 있습니다.

time.sleep: 잠시 멈추기

time.sleep(초)는 프로그램을 지정한 시간만큼 멈춥니다. 재시도 간격, 속도 제한 등에 씁니다.

PYTHON
import time

print("시작")
time.sleep(1)       # 1초 대기
print("1초 후")

나쁜 예 ❌ vs 좋은 예 ✅

PYTHON
# ❌ 나쁜 예: 날짜를 문자열로 직접 계산
date_str = "2025-12-31"
# "다음 날"을 구하려면? 31 다음은 32가 아니라 다음 달 1일...
# 문자열로는 월말·연말·윤년 처리가 악몽

# ✅ 좋은 예: datetime에 맡기기
from datetime import datetime, timedelta
dt = datetime.strptime("2025-12-31", "%Y-%m-%d")
next_day = dt + timedelta(days=1)
print(next_day.strftime("%Y-%m-%d"))    # 2026-01-01   (정확!)

이 장에서 배운 것

  • 날짜·시간은 datetime 모듈에 맡긴다. date(날짜), datetime(날짜+시간), timedelta(간격).
  • timedelta로 계산한다: 날짜 ± 간격 = 날짜, 날짜 − 날짜 = 간격(.days).
  • strftime(날짜→문자열, 만들기)과 strptime(문자열→날짜, 파싱). %Y-%m-%d 형식 기호를 쓴다.
  • 타임존zoneinfo로 다룬다. UTC로 저장하고 표시할 때 변환하는 것이 정석이다.
  • 코드 실행 시간은 time.perf_counter()로 측정한다. time.sleep()으로 잠시 멈춘다.

🧪 실습 문제

문제 1. date를 이용해 2025년 12월 25일이 무슨 요일인지 weekday()로 출력하세요. (월=0 기준)

문제 2. 오늘부터 100일 후의 날짜를 구하는 코드를 작성하세요. (date.today()timedelta)

문제 3. 다음 두 날짜 사이가 며칠 차이인지 출력하세요.

PYTHON
from datetime import date
d1 = date(2025, 1, 1)
d2 = date(2025, 12, 31)

문제 4. datetime(2025, 7, 15, 9, 5)strftime으로 2025/07/15 09:05 형식의 문자열로 만드세요.

문제 5. 문자열 "2025-06-24 18:30"strptime으로 datetime 객체로 바꾼 뒤, 30분을 더해 출력하세요.

<details>

<summary>✅ 정답·해설 보기</summary>

1.

PYTHON
from datetime import date
d = date(2025, 12, 25)
print(d.weekday())   # 3 (목요일)

2.

PYTHON
from datetime import date, timedelta
print(date.today() + timedelta(days=100))

3.

PYTHON
from datetime import date
d1 = date(2025, 1, 1)
d2 = date(2025, 12, 31)
print((d2 - d1).days)   # 364

4.

PYTHON
from datetime import datetime
dt = datetime(2025, 7, 15, 9, 5)
print(dt.strftime("%Y/%m/%d %H:%M"))   # 2025/07/15 09:05

5.

PYTHON
from datetime import datetime, timedelta
dt = datetime.strptime("2025-06-24 18:30", "%Y-%m-%d %H:%M")
print(dt + timedelta(minutes=30))   # 2025-06-24 19:00:00

</details>

◀️ 이전 장: 22. 로깅 | ▶️ 다음 장: 24. 동시성 기초