将月份转换为数字时如何有效地检查不同的日期格式

时间:2019-06-28 17:13:11

标签: python python-3.x datetime conditional-statements try-except

我正在尝试将给定的月份转换为整数格式的月份数。我想尝试转换三种有效格式。以字符串形式给出的月份数字(输入函数返回字符串),月份的缩写和完整的月份名称。

尽管我的功能按预期工作,但我仍然觉得它写得不好,尽管我试图使其尽可能地简洁。特别是,我对刚刚通过的除外声明感到不满意。既要处理字符串转换为整数,又要检查字符串是否是有效月份以转换为整数,这是一项艰巨的任务。

我试图更改try-excepts的顺序,删除了字符串到int以使其位于try-except块上,而没有直接进入异常中的日期格式,但仅此而已。下面的功能是我的最佳尝试。除了创建辅助函数外,我什么都没想到?

代码

def get_start_month_updated():
    date_formats = ['%b', '%B']
    while True:
        month = input("What is the starting month?")
        try:
            month_num = int(month)
            if 1 <= month_num <= 12:
                return month_num
        except ValueError:
            for date_format in date_formats:
                try:
                    month_num = strptime(month, date_format).tm_mon
                    return month_num
                except ValueError:
                    pass
            else:
                print("You must enter a valid month")
        else:
            print("You must enter a valid month")

我的结果是正确的,并且该功能可以按预期工作,但是我觉得代码很混乱,并且有一种更好的方法来完成此操作而不会感到费解。

1 个答案:

答案 0 :(得分:1)

首先,您应该创建一个 parse_month 函数以进行更好的测试。 此 parse_month 函数可以具有多个内部解析器,每个内部解析器一种:“ int”,datetime和“%b”,datetime和“%B”。这是实现细节。

做到这一点的一种方法是:

import datetime
import functools


def parse_month(value):
    def from_int(v):
        month_num = int(v)
        if 1 <= month_num <= 12:
            return month_num
        raise ValueError(v)

    def from_month_fmt(fmt, v):
        return datetime.datetime.strptime(v, fmt).month

    parsers = (
        from_int,
        functools.partial(from_month_fmt, "%b"),
        functools.partial(from_month_fmt, "%B"),
    )
    for parser in parsers:
        try:
            return parser(value)
        except ValueError:
            pass
    else:
        raise ValueError(value)

然后,您可以使用此功能来提示用户:

def get_start_month_updated():
    while True:
        month = input("What is the starting month?")
        try:
            month_num = parse_month(month)
        except ValueError:
            print("You must enter a valid month")
        else:
            return month_num

如果您不想重新发明轮子,Arrow是您的朋友:

import arrow

def parse_month(value):
    formats = (
        "MMMM",
        "MMM",
        "MM",
        "M"
    )
    for fmt in formats:
        try:
            return arrow.get(value, fmt).month
        except arrow.parser.ParserError:
            pass
    else:
        raise ValueError(value)