# Python datetime 与时间处理

## 学习目标
- 掌握 `datetime` 模块的核心类
- 学会时间格式化与解析
- 理解时区处理
- 掌握时间计算和比较

---

## 1. datetime 核心类

```python
from datetime import datetime, date, time, timedelta

# date - 日期（年月日）
d = date(2024, 1, 15)
print(d)          # 2024-01-15
print(d.year)     # 2024
print(d.month)    # 1
print(d.day)      # 15

# time - 时间（时分秒微秒）
t = time(14, 30, 45, 123456)
print(t)          # 14:30:45.123456
print(t.hour)     # 14
print(t.minute)   # 30

# datetime - 日期时间
dt = datetime(2024, 1, 15, 14, 30, 45)
print(dt)         # 2024-01-15 14:30:45
```

### 1.1 获取当前时间

```python
from datetime import datetime, date

# 当前日期时间
now = datetime.now()
print(f"现在: {now}")

# 当前日期
today = date.today()
print(f"今天: {today}")

# 时间戳转 datetime
timestamp = 1705312245
dt = datetime.fromtimestamp(timestamp)
print(f"时间戳转换: {dt}")

# datetime 转时间戳
ts = datetime.now().timestamp()
print(f"当前时间戳: {ts}")
```

---

## 2. 格式化与解析

### 2.1 strftime - 格式化输出

```python
from datetime import datetime

now = datetime.now()

# 常用格式
print(now.strftime("%Y-%m-%d"))           # 2024-01-15
print(now.strftime("%H:%M:%S"))           # 14:30:45
print(now.strftime("%Y-%m-%d %H:%M:%S"))  # 2024-01-15 14:30:45
print(now.strftime("%A, %B %d, %Y"))      # Monday, January 15, 2024

# 格式说明符
# %Y - 四位年份  %y - 两位年份
# %m - 月份(01-12)  %d - 日期(01-31)
# %H - 小时(00-23)  %M - 分钟(00-59)  %S - 秒(00-59)
# %A - 星期全称    %a - 星期缩写
# %B - 月份全称    %b - 月份缩写
```

### 2.2 strptime - 字符串解析

```python
from datetime import datetime

# 解析日期字符串
date_str = "2024-01-15 14:30:00"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(dt)  # 2024-01-15 14:30:00

# 解析不同格式
date_str2 = "15/01/2024"
dt2 = datetime.strptime(date_str2, "%d/%m/%Y")
print(dt2)  # 2024-01-15 00:00:00

# 解析带时区的 ISO 格式
dt3 = datetime.fromisoformat("2024-01-15T14:30:00")
print(dt3)
```

---

## 3. 时间计算

### 3.1 timedelta - 时间差

```python
from datetime import datetime, timedelta

now = datetime.now()

# 加法
future = now + timedelta(days=7)
print(f"7天后: {future}")

# 减法
past = now - timedelta(hours=3)
print(f"3小时前: {past}")

# 时间差计算
dt1 = datetime(2024, 1, 15)
dt2 = datetime(2024, 2, 20)
diff = dt2 - dt1
print(f"相差: {diff.days} 天")

# timedelta 属性
print(f"总秒数: {diff.total_seconds()}")

# 复杂计算
print(now + timedelta(weeks=2, days=3, hours=5))
```

### 3.2 日期比较

```python
from datetime import datetime

d1 = datetime(2024, 1, 15)
d2 = datetime(2024, 2, 20)

print(d1 < d2)    # True
print(d1 == d2)   # False
print(d1 != d2)   # True

# 判断日期范围
now = datetime.now()
start = datetime(2024, 1, 1)
end = datetime(2024, 12, 31)

if start <= now <= end:
    print("当前时间在范围内")
```

---

## 4. 时区处理

### 4.1 使用 datetime.timezone

```python
from datetime import datetime, timezone, timedelta

# UTC 时间
utc_now = datetime.now(timezone.utc)
print(f"UTC: {utc_now}")

# 创建指定时区
china_tz = timezone(timedelta(hours=8))
beijing_time = datetime.now(china_tz)
print(f"北京时间: {beijing_time}")

# 转换时区
utc_dt = datetime(2024, 1, 15, 14, 30, tzinfo=timezone.utc)
local_dt = utc_dt.astimezone(china_tz)
print(f"UTC: {utc_dt}")
print(f"北京: {local_dt}")
```

### 4.2 使用 pytz（第三方库）

```python
# pip install pytz
# import pytz
# 
# # 常见时区
# utc = pytz.utc
# beijing = pytz.timezone('Asia/Shanghai')
# new_york = pytz.timezone('America/New_York')
# 
# # 带时区的当前时间
# now = datetime.now(beijing)
# print(now)
# 
# # 转换时区
# ny_time = now.astimezone(new_york)
# print(ny_time)
```

### 4.3 使用 zoneinfo（Python 3.9+）

```python
from datetime import datetime
from zoneinfo import ZoneInfo

# 创建带时区的时间
beijing = ZoneInfo("Asia/Shanghai")
ny = ZoneInfo("America/New_York")

dt = datetime(2024, 1, 15, 14, 30, tzinfo=beijing)
print(f"北京: {dt}")

# 转换到纽约
ny_dt = dt.astimezone(ny)
print(f"纽约: {ny_dt}")
```

---

## 5. 实用工具

### 5.1 日期范围生成

```python
from datetime import datetime, timedelta

def date_range(start, end, step=1):
    """生成日期范围"""
    current = start
    while current <= end:
        yield current
        current += timedelta(days=step)

# 使用
start = datetime(2024, 1, 1)
end = datetime(2024, 1, 10)

for d in date_range(start, end):
    print(d.strftime("%Y-%m-%d"))
```

### 5.2 人性化时间显示

```python
from datetime import datetime, timedelta

def human_time(dt):
    """人性化时间显示"""
    now = datetime.now()
    diff = now - dt
    
    if diff < timedelta(minutes=1):
        return "刚刚"
    elif diff < timedelta(hours=1):
        return f"{diff.seconds // 60} 分钟前"
    elif diff < timedelta(days=1):
        return f"{diff.seconds // 3600} 小时前"
    elif diff < timedelta(days=7):
        return f"{diff.days} 天前"
    else:
        return dt.strftime("%Y-%m-%d")

# 测试
print(human_time(datetime.now() - timedelta(minutes=5)))   # 5 分钟前
print(human_time(datetime.now() - timedelta(hours=3)))     # 3 小时前
print(human_time(datetime.now() - timedelta(days=2)))      # 2 天前
print(human_time(datetime(2023, 1, 1)))                     # 2023-01-01
```

### 5.3 日历操作

```python
import calendar

# 打印月历
print(calendar.month(2024, 1))

# 判断闰年
print(calendar.isleap(2024))  # True
print(calendar.isleap(2023))  # False

# 星期几（0=周一）
print(calendar.weekday(2024, 1, 15))  # 0（周一）

# 月份天数
print(calendar.monthrange(2024, 2))  # (3, 29) - 周四开始，29天

# 迭代月份
cal = calendar.Calendar()
for week in cal.monthdayscalendar(2024, 1):
    print(week)
```

---

## 6. 时间性能测量

```python
import time
from datetime import datetime

# 简单计时
start = time.time()
# ... 执行代码 ...
time.sleep(0.1)
elapsed = time.time() - start
print(f"耗时: {elapsed:.4f} 秒")

# 更精确的时间
start = time.perf_counter()
# ... 执行代码 ...
time.sleep(0.1)
elapsed = time.perf_counter() - start
print(f"精确耗时: {elapsed:.6f} 秒")

# 程序运行时间
print(f"程序运行时间: {time.process_time():.4f} 秒")
```

---

## 本节小结

- **datetime**：`date`、`time`、`datetime` 三个核心类
- **格式化**：`strftime`（格式化）、`strptime`（解析）
- **计算**：`timedelta` 进行日期时间加减
- **时区**：`timezone`、`zoneinfo`（3.9+）、`pytz`
- **工具**：`calendar` 模块处理日历相关操作
- **性能**：`time.perf_counter()` 精确计时

---

## 练习

1. 编写函数，计算两个日期之间的工作日天数（排除周末）
2. 实现一个倒计时器，接受目标时间并每秒打印剩余时间
3. 编写日期解析函数，支持多种常见格式自动识别
4. 创建一个定时任务调度器，支持按天/周/月执行回调

