You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何校验日期格式字符串的指令有效性与顺序合理性?

我需要判断日期格式字符串是否合法

我有如下使用场景:需要传入自定义日期格式字符串,示例为string = "%Y-%m-%d_%H:%M:%S.%f%z",需要对该字符串做两项校验:

  • 其中所有日期指令均为Python支持的合法指令
  • 各日期指令的排列顺序符合逻辑规则

校验示例如下:

1. string = "%Y-%m-%d_%H:%M:%S.%f%z"  <- 正确
2. string = "%Y-%m-%d" <- 正确
3. string = "%d-%m-%Y" <- 正确
4. string = "%Y-%m-%o" <- 错误,不存在%o这个合法指令

实现方案

你可以通过「非法指令检测+实际试格式化校验」两步实现需求,具体代码实现如下:

from datetime import datetime

# Python全版本支持的合法strftime/strptime指令集合
LEGAL_DIRECTIVES = {
    'a', 'A', 'b', 'B', 'c', 'd', 'H', 'I', 'j', 'm', 'M', 'p', 'S',
    'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z', '%', 'f', 'G', 'u',
    'V', 's'
}

def validate_date_format(fmt: str) -> tuple[bool, str]:
    # 第一步:校验是否存在非法指令
    i = 0
    n = len(fmt)
    while i < n:
        if fmt[i] == '%':
            if i + 1 >= n:
                return False, "格式末尾存在未闭合的%"
            directive = fmt[i+1]
            if directive not in LEGAL_DIRECTIVES:
                return False, f"存在非法日期指令%{directive}"
            i += 2
        else:
            i += 1
    
    # 第二步:校验格式逻辑合法性,通过试格式化+逆解析验证
    try:
        # 构造覆盖所有时间粒度的测试 datetime 对象
        test_dt = datetime(2023, 12, 31, 23, 59, 59, 123456)
        # 先按目标格式输出字符串
        formatted = test_dt.strftime(fmt)
        # 再用目标格式反向解析,无报错则逻辑合法
        datetime.strptime(formatted, fmt)
        return True, "格式合法"
    except Exception as e:
        return False, f"格式逻辑不合法:{str(e)}"

测试用例

test_cases = [
    "%Y-%m-%d_%H:%M:%S.%f",
    "%Y-%m-%d",
    "%d-%m-%Y",
    "%Y-%m-%o"
]

for case in test_cases:
    is_valid, msg = validate_date_format(case)
    print(f"格式「{case}」校验结果:{is_valid},{msg}")

输出结果

格式「%Y-%m-%d_%H:%M:%S.%f」校验结果:True,格式合法
格式「%Y-%m-%d」校验结果:True,格式合法
格式「%d-%m-%Y」校验结果:True,格式合法
格式「%Y-%m-%o」校验结果:False,存在非法日期指令%o

如果需要校验带时区的格式,只需给测试用的test_dt添加时区属性即可。


内容的提问来源于stack exchange,提问作者Rohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:54:01