
Polars 的 str.strptime() 不支持 %q 等季度占位符,需通过正则提取年/季度、计算季度起始日,并结合天数偏移构造准确日期。本文提供纯表达式、零 Python UDF 的高效列式处理方案。
polars 的 `str.strptime()` 不支持 `%q` 等季度占位符,需通过正则提取年/季度、计算季度起始日,并结合天数偏移构造准确日期。本文提供纯表达式、零 python udf 的高效列式处理方案。
在 Polars 中,直接使用 str.strptime() 解析类似 "2023-Q3" 或 "2023-Q3-27" 这类含季度标识(Q1–Q4)的字符串会返回 null,根本原因在于:底层依赖的 Rust chrono 库虽支持 %q 格式化输出,但不支持其作为输入解析器(即 strptime 语义)。因此,"%Y-Q%q" 或 "%Y-Q%q-%d" 等格式无法被正确识别,即使启用 strict=False 也无效。
解决该问题的关键是放弃依赖 strptime,转而采用 纯 Polars 表达式链式处理——利用正则提取、算术推导与日期运算,在不调用 Python 函数、不触发行式迭代的前提下,高效完成转换。整个流程分为三步:
-
结构化解析:用
str.extract()分别捕获年份(4位数字)、季度编号(Q 后数字)和可选的“本季度第 N 天”; -
推导季度起始日:根据年份和季度计算该季度首月(如 Q3 → 7 月),再用
pl.date(year, month, 1)构建起始日期; -
动态偏移修正:若原始字符串含
-N(如-27),将其解释为“从季度首日起的第 N 天”,减 1 后转为pl.duration(days=...)并相加。
以下是完整、健壮的实现代码(兼容 2025-Q4 和 2023-Q3-45 等混合格式):
import polars as pl
df = pl.DataFrame({
"quarter_str": ["2023-Q3-01", "2023-Q3-27", "2025-Q4", "2025-Q3-45"]
})
# 步骤 1:提取核心字段(自动处理缺失 day 部分)
quarter = pl.col("quarter_str").str.extract(r"Q(\d)").cast(pl.Int8) # 提取 Q 后数字
year = pl.col("quarter_str").str.extract(r"(\d{4})").cast(pl.Int16) # 提取 4 位年份
day_of_quarter = (
pl.col("quarter_str")
.str.extract(r"-(\d+)$") # 匹配末尾的 -数字
.fill_null("1") # 若无 day,默认为 1(即季度首日)
.cast(pl.Int16)
)
# 步骤 2:计算季度起始月份(Q1→1月,Q2→4月…)
month = (quarter - 1) * 3 + 1
# 步骤 3:构建季度首日 + 偏移天数(注意:第1天对应 +0 天)
quarter_start = pl.date(year, month, 1)
parsed_date = quarter_start + pl.duration(days=day_of_quarter - 1)
result = df.with_columns(parsed_date.alias("parsed_date"))
print(result)
✅ 输出结果:
shape: (4, 2) ┌─────────────┬─────────────┐ │ quarter_str ┆ parsed_date │ │ --- ┆ --- │ │ str ┆ date │ ╞═════════════╪═════════════╡ │ 2023-Q3-01 ┆ 2023-07-01 │ │ 2023-Q3-27 ┆ 2023-07-27 │ │ 2025-Q4 ┆ 2025-10-01 │ │ 2025-Q3-45 ┆ 2025-08-14 │ └─────────────┴─────────────┘
? 注意事项与最佳实践:
- 所有操作均为 lazy、向量化、无 UDF,性能远优于
apply()或map_elements(); - 正则使用原始字符串
r"..."避免转义错误;str.extract默认返回null(非匹配项),配合fill_null()可安全处理缺失 day; -
day_of_quarter - 1是关键:因pl.date(...)已表示季度第 1 天,故第 N 天需加N-1天; - 若需支持更多格式(如
2023Q3无短横线),仅需调整正则模式(例如r"(\d{4})Q(\d)"); - 该方案天然兼容 Polars LazyFrame,可无缝嵌入大规模 ETL 流程。
此方法不仅解决了季度解析难题,更体现了 Polars “以表达式为中心”的高性能数据处理哲学——用声明式逻辑替代命令式循环,兼顾可读性与执行效率。










