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

如何确定指定timestamp与格式字符串对应的datetime取值范围

实现方案

核心思路

  1. 直接用datetime.strptime()解析得到时间范围的最小值(下界),这部分符合原生方法的默认逻辑,无需修改。
  2. 用带负向断言的正则表达式提取格式字符串中所有非转义的格式码,自动跳过%%转义的字面量百分号场景,不需要手动全量解析格式串。
  3. 根据提取到的格式码判断当前时间的最高精度,基于最高精度计算上界:最小值加1个对应精度单位,再减去1个最小时间单位(微秒/秒可根据需求自定义)。

代码实现(依赖dateutil处理年月偏移)

该方案用dateutil.relativedelta处理年月级别的偏移,避免了手动处理闰年、月末等边界场景的问题,稳定性更高。

from datetime import datetime
from dateutil.relativedelta import relativedelta
import re

# 格式码对应精度优先级,数值越大精度越高
FORMAT_PRECISION = {
    # 年相关格式码
    'Y': 1, 'y': 1,
    # 月相关格式码
    'm': 2, 'b': 2, 'B': 2,
    # 日相关格式码
    'd': 3, 'j': 3, 'w': 3, 'U': 3, 'W': 3,
    # 时相关格式码
    'H': 4, 'I': 4, 'p': 4,
    # 分相关格式码
    'M': 5,
    # 秒相关格式码
    'S': 6,
    # 微秒相关格式码
    'f': 7
}
# 精度对应的偏移参数
PRECISION_DELTA = {
    1: {'years': 1},
    2: {'months': 1},
    3: {'days': 1},
    4: {'hours': 1},
    5: {'minutes': 1},
    6: {'seconds': 1},
    7: {'microseconds': 1}
}

def get_datetime_range(timestamp: str, fmt: str) -> tuple[datetime, datetime]:
    # 计算下界
    min_dt = datetime.strptime(timestamp, fmt)
    # 提取所有非转义的格式码,自动跳过%%转义场景
    format_codes = re.findall(r'(?<!%)%([a-zA-Z])', fmt)
    # 确定最高精度
    max_precision = max(FORMAT_PRECISION[code] for code in format_codes if code in FORMAT_PRECISION)
    # 计算上界:加1个精度单位后减1微秒,不需要微秒可改成减1秒
    delta = relativedelta(**PRECISION_DELTA[max_precision])
    max_dt = min_dt + delta - relativedelta(microseconds=1)
    return min_dt, max_dt

测试示例

# 示例1:年精度
print(get_datetime_range('2020', '%Y'))
# 输出:(datetime.datetime(2020, 1, 1, 0, 0), datetime.datetime(2020, 12, 31, 23, 59, 59, 999999))

# 示例2:日精度
print(get_datetime_range('2020-01-01', '%Y-%m-%d'))
# 输出:(datetime.datetime(2020, 1, 1, 0, 0), datetime.datetime(2020, 1, 1, 23, 59, 59, 999999))

# 示例3:带%%转义的格式
print(get_datetime_range('2020%05', '%Y%%%m'))
# 格式串实际匹配"年+%+月",精度为月,输出:(datetime.datetime(2020, 5, 1, 0, 0), datetime.datetime(2020, 5, 31, 23, 59, 59, 999999))

无第三方依赖的简化实现

如果不想引入dateutil依赖,可以手动处理年月偏移,其他精度直接用原生timedelta计算即可:

from datetime import datetime, timedelta
import re

FORMAT_PRECISION = {
    'Y': 1, 'y': 1, 'm': 2, 'b': 2, 'B': 2, 'd': 3, 'j': 3, 'w': 3, 'U': 3, 'W': 3,
    'H': 4, 'I':4, 'p':4, 'M':5, 'S':6, 'f':7
}

def get_datetime_range(timestamp: str, fmt: str) -> tuple[datetime, datetime]:
    min_dt = datetime.strptime(timestamp, fmt)
    format_codes = re.findall(r'(?<!%)%([a-zA-Z])', fmt)
    max_precision = max(FORMAT_PRECISION[code] for code in format_codes if code in FORMAT_PRECISION)
    
    if max_precision == 1:
        next_dt = min_dt.replace(year=min_dt.year + 1)
    elif max_precision == 2:
        if min_dt.month == 12:
            next_dt = min_dt.replace(year=min_dt.year + 1, month=1)
        else:
            next_dt = min_dt.replace(month=min_dt.month + 1)
    elif max_precision == 3:
        next_dt = min_dt + timedelta(days=1)
    elif max_precision == 4:
        next_dt = min_dt + timedelta(hours=1)
    elif max_precision == 5:
        next_dt = min_dt + timedelta(minutes=1)
    elif max_precision == 6:
        next_dt = min_dt + timedelta(seconds=1)
    else:
        next_dt = min_dt + timedelta(microseconds=1)
    
    max_dt = next_dt - timedelta(microseconds=1)
    return min_dt, max_dt

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:09:03