1. 计算年龄/工龄(精确到年)

from datetime import date
 
def calculate_age(birth: date, as_of: date = None) -> int:
    """计算周岁"""
    today = as_of or date.today()
    age = today.year - birth.year
    # 如果今年生日还没过,减1
    if (today.month, today.day) < (birth.month, birth.day):
        age -= 1
    return age
 
# 使用:calculate_age(date(1990, 8, 15))

2. 合同到期日计算(加上N个月/年,保持月末逻辑)

from dateutil.relativedelta import relativedelta  # 需 pip install python-dateutil
 
expiry = datetime(2025, 1, 31) + relativedelta(months=6)  # 2025-07-31
# 如果是月末则保持月末
expiry = datetime(2025, 1, 31) + relativedelta(months=1)  # 2025-02-28

若不使用 dateutil,纯 datetime 加月需自行处理:

def add_months(dt: datetime, months: int) -> datetime:
    month = dt.month - 1 + months
    year = dt.year + month // 12
    month = month % 12 + 1
    day = min(dt.day, [31,29 if year%4==0 and (year%100!=0 or year%400==0) else 28,31,30,31,30,31,31,30,31,30,31][month-1])
    return dt.replace(year=year, month=month, day=day)

3. 计算两个日期之间的工作日天数

import numpy as np
 
workdays = np.busday_count('2025-05-01', '2025-05-31')  # 不含起,含止?默认不含结束日,需 +1
# 若包含起始日
workdays = np.busday_count('2025-05-01', '2025-05-31') + 1
 
# 自定义节假日
holidays = ['2025-05-01', '2025-05-02']
workdays = np.busday_count('2025-05-01', '2025-05-31', holidays=holidays)

用 Pandas:

import pandas as pd
bd_range = pd.bdate_range(start='2025-05-01', end='2025-05-31', freq='C', holidays=holidays)
len(bd_range)

4. 找出下一个工作日(跳过周末和节假日)

def next_business_day(start_date, holidays=None):
    holidays = holidays or []
    day = start_date + timedelta(days=1)
    while day.weekday() >= 5 or day in holidays:
        day += timedelta(days=1)
    return day

5. 获取某月最后一天 / 季度末

# 当月最后一天
import calendar
_, last_day = calendar.monthrange(2025, 2)  # 返回(第一天星期, 最后一天)
date(2025, 2, last_day)
 
# 或用 Pandas
pd.Timestamp('2025-02-01') + pd.offsets.MonthEnd(1)  # 2025-02-28
# 季度末
pd.Timestamp('2025-05-20') + pd.offsets.QuarterEnd(startingMonth=1)  # 3月底

6. 日期分组(按周/月/季度/年)并汇总

df['order_date'] = pd.to_datetime(df['order_date'])
# 增加月份标签
df['month'] = df['order_date'].dt.to_period('M')   # 2025-05
# 按周聚合销售额
weekly_sales = df.groupby(pd.Grouper(key='order_date', freq='W-MON'))['amount'].sum()

7. 计算时间间隔(小时、分钟)

start = datetime(2025,5,20,9,0)
end = datetime(2025,5,20,17,30)
diff = end - start
hours = diff.total_seconds() / 3600   # 8.5 小时

8. 从 Excel 序列号转换日期

Excel 整数日期序列号是基于 1900-01-01 的天数(有 1900 年闰年 bug 注意):

def excel_serial_to_date(serial):
    """将 Excel 序列号转为 date,支持整数和浮点(含时间)"""
    if pd.isna(serial):
        return pd.NaT
    # Excel 日期基准:1899-12-30
    return pd.Timestamp('1899-12-30') + pd.Timedelta(days=serial)

9. 两个时间段是否重叠

def is_overlap(start1, end1, start2, end2):
    return max(start1, start2) < min(end1, end2)

10. 时间序列填充缺失日期(补全日历)

all_dates = pd.date_range(start=df['date'].min(), end=df['date'].max(), freq='D')
df_full = df.set_index('date').reindex(all_dates).fillna(0).reset_index()