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

如何定义Hypothesis策略生成兼容datetime.strptime的随机日期时间格式?

构建兼容datetime.strptime的Hypothesis日期时间格式生成策略

核心前提

我们需要生成的格式字符串fmt必须满足:用当前时间执行strftime(fmt)得到的字符串,能被strptime用同一个fmt正确解析且无报错。这意味着要避开那些仅在strftime中可用但strptime不支持的格式符,同时确保组合后的格式不会触发解析异常。

步骤1:定义安全的格式符与预定义片段

先列出strftime和strptime双向兼容的格式符,并组合成经过验证的常用片段,减少无效格式的生成:

from hypothesis import strategies as st
import datetime as dt

# 预定义日期格式片段:涵盖主流日期表示方式
date_fragments = st.sampled_from([
    "%Y-%m-%d",
    "%d/%m/%Y",
    "%m/%d/%Y",
    "%b %d, %Y",
    "%B %d, %Y",
    "%Y/%m/%d",
    "%d-%m-%Y",
])

# 预定义时间格式片段:覆盖24小时制、12小时制等场景
time_fragments = st.sampled_from([
    "%H:%M:%S",
    "%H:%M",
    "%I:%M %p",
    "%I:%M:%S %p",
    "%H.%M.%S",
])

步骤2:构建灵活的随机格式生成策略

如果需要更具随机性的格式(而非仅预定义片段),可以组合单个格式符与合法分隔符:

# 单个日期格式符(双向兼容)
date_tokens = st.sampled_from(["%Y", "%m", "%d", "%b", "%B", "%a", "%A"])
# 单个时间格式符(双向兼容)
time_tokens = st.sampled_from(["%H", "%I", "%M", "%S", "%p"])
# 合法分隔符:避免与格式符冲突
separators = st.sampled_from(["-", "/", ":", ".", " ", ", "])

# 生成随机日期格式:确保是「格式符+分隔符+格式符」的交替结构
random_date_format = st.builds(
    lambda parts: "".join(parts),
    st.lists(
        st.one_of(date_tokens, separators),
        min_size=3, max_size=7,
        unique_by=lambda x: x in date_tokens  # 防止连续出现分隔符
    )
)

# 生成随机时间格式:逻辑同随机日期格式
random_time_format = st.builds(
    lambda parts: "".join(parts),
    st.lists(
        st.one_of(time_tokens, separators),
        min_size=3, max_size=7,
        unique_by=lambda x: x in time_tokens
    )
)

# 组合日期、时间格式,支持单独日期/时间或两者结合
datetime_format = st.one_of(
    date_fragments,
    time_fragments,
    st.builds(
        lambda d, sep, t: f"{d}{sep}{t}",
        date_fragments,
        st.sampled_from([" ", " at ", " "]),
        time_fragments
    ),
    st.builds(
        lambda d, sep, t: f"{d}{sep}{t}",
        random_date_format,
        st.sampled_from([" ", " at ", " "]),
        random_time_format
    )
)

步骤3:过滤不兼容格式

即使基于安全格式符生成的格式,也可能存在个别无效组合(比如%p未搭配%I使用)。通过过滤函数验证格式的双向兼容性:

def is_compatible_format(fmt):
    try:
        now = dt.datetime.now()
        formatted_str = now.strftime(fmt)
        dt.datetime.strptime(formatted_str, fmt)
        return True
    except (ValueError, TypeError):
        return False

# 最终的兼容格式策略
compatible_datetime_formats = datetime_format.filter(is_compatible_format)

使用示例

可以直接用该策略生成测试用例,验证格式的有效性:

@st.composite
def datetime_with_valid_format(draw):
    fmt = draw(compatible_datetime_formats)
    now = dt.datetime.now()
    formatted_str = now.strftime(fmt)
    parsed_dt = dt.datetime.strptime(formatted_str, fmt)
    return (fmt, now, formatted_str, parsed_dt)

# 生成5个示例验证
for _ in range(5):
    fmt, original, formatted, parsed = datetime_with_valid_format().example()
    print(f"格式: {fmt}")
    print(f"原时间: {original}")
    print(f"格式化后: {formatted}")
    print(f"解析后: {parsed}")
    print("---")

关键注意事项

  • 避免使用%c、%x、%X这类依赖系统区域设置的格式符,不同环境下解析规则不一致,易触发兼容性问题。
  • %p必须搭配%I(12小时制小时)使用,否则strptime会报错,过滤函数会自动排除这类无效组合。
  • 若需扩展格式范围,新增格式符前务必确认其在strftime和strptime中均受支持。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 15:27:34