3Python Cookbook(第3版)

数字、日期与时间

数值计算

decimaldatetime时区处理大数运算

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第3章:数字、日期与时间

一、导读

1.1 本章学习目标

第3章讲解 Python 中数字和日期时间的处理技巧:decimal 精确计算、datetime 时区处理。

本章核心学习目标:

  • 掌握 decimal 模块:精确的浮点运算
  • 理解 datetime 和时区:正确处理时间
  • 掌握日期运算:timedelta、relativedelta

1.2 为什么本章如此重要

浮点精度和时区是编程中最容易出错的两个领域。Python 提供了专门的模块来处理这些问题。

1.3 核心问题引导

为什么 0.1 + 0.2 ≠ 0.3?如何解决?

如何处理不同时区的时间转换?

如何计算两个日期之间的工作日数?


二、核心概念详解

2.1 精确浮点运算

python
from decimal import Decimal, getcontext

# 浮点精度问题
print(0.1 + 0.2)           # 0.30000000000000004
print(0.1 + 0.2 == 0.3)    # False

# 使用 Decimal
a = Decimal('0.1')
b = Decimal('0.2')
print(a + b)               # 0.3
print(a + b == Decimal('0.3'))  # True

# 设置精度
getcontext().prec = 50
print(Decimal(1) / Decimal(7))  # 0.14285714285714285714285714285714285714285714285714

# 金融计算
price = Decimal('19.99')
tax_rate = Decimal('0.0825')
total = price * (1 + tax_rate)
print(f"Total: ${total:.2f}")  # Total: $21.64

2.2 日期与时间

python
from datetime import datetime, timedelta, timezone
import zoneinfo

# 当前时间
now = datetime.now()
utc_now = datetime.now(timezone.utc)

# 时区转换
tokyo_tz = zoneinfo.ZoneInfo('Asia/Tokyo')
tokyo_time = utc_now.astimezone(tokyo_tz)
print(f"Tokyo: {tokyo_time}")

# 日期运算
tomorrow = now + timedelta(days=1)
next_week = now + timedelta(weeks=1)
diff = tomorrow - now
print(f"Diff: {diff.days} days")

# 日期解析
from dateutil import parser
dt = parser.parse("March 15, 2024 3:30 PM")
print(dt)  # 2024-03-15 15:30:00

# 格式化
print(now.strftime("%Y-%m-%d %H:%M:%S"))
print(now.isoformat())

2.3 工作日计算

python
from datetime import date, timedelta

def workdays_between(start, end):
    """计算两个日期之间的工作日数"""
    days = 0
    current = start
    while current <= end:
        if current.weekday() < 5:  # 周一到周五
            days += 1
        current += timedelta(days=1)
    return days

start = date(2024, 1, 1)
end = date(2024, 1, 31)
print(f"Workdays: {workdays_between(start, end)}")  # 23

三、实战案例

3.1 案例一:时区安全的日程管理

python
from datetime import datetime
import zoneinfo

class Scheduler:
    def __init__(self, default_tz='UTC'):
        self.default_tz = zoneinfo.ZoneInfo(default_tz)
        self.events = []
    
    def add_event(self, title, start_str, tz_str=None):
        tz = zoneinfo.ZoneInfo(tz_str) if tz_str else self.default_tz
        start = datetime.fromisoformat(start_str).replace(tzinfo=tz)
        self.events.append({'title': title, 'start': start})
    
    def list_events(self, tz_str='UTC'):
        tz = zoneinfo.ZoneInfo(tz_str)
        for event in sorted(self.events, key=lambda e: e['start']):
            local_start = event['start'].astimezone(tz)
            print(f"{event['title']}: {local_start.strftime('%Y-%m-%d %H:%M %Z')}")

scheduler = Scheduler()
scheduler.add_event("Team Meeting", "2024-03-15 10:00:00", "America/New_York")
scheduler.add_event("Code Review", "2024-03-15 14:00:00", "Asia/Tokyo")

print("New York time:")
scheduler.list_events("America/New_York")
print("\nTokyo time:")
scheduler.list_events("Asia/Tokyo")

四、本章小结

Decimal 提供精确的浮点运算,适合金融计算

datetime + zoneinfo 正确处理时区

timedelta 支持日期运算


五、思考与练习

为什么应该总是使用带时区的 datetime?

如何处理夏令时(DST)的转换?


3/12数字、日
0%