简体   繁体   English

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

[英]How to efficiently check different date formats when converting month to number

I'm trying to convert a given month to a month number in integer format. 我正在尝试将给定的月份转换为整数格式的月份数。 There are three valid formats that I want to try to convert. 我想尝试转换三种有效格式。 A month number that's given as a string (input function returns a string), a month abbreviation, and a full month name. 以字符串形式给出的月份数字(输入函数返回字符串),月份的缩写和完整的月份名称。

While my function works as intended I feel like it's not that well written, despite my attempts to make it as clean as possible. 尽管我的功能按预期工作,但我仍尝试编写不太干净的方法,但感觉却不太好。 In particular, I'm not happy that I have an except statement that just passes. 特别是,我对刚刚通过的除外声明感到不满意。 Handling both a string conversion to an integer AND checking to see if the string is a valid month to convert to an integer was a tough task. 既要处理字符串转换为整数,又要检查字符串是否是有效月份以转换为整数,这是一项艰巨的任务。

I tried to change the order of the try-excepts, removing the string-to-int to make it's on try-except block without going straight into the date formatting in the exception but that's about it. 我试图更改try-excepts的顺序,删除了字符串到int以使其位于try-except块上,而没有直接进入异常中的日期格式,仅此而已。 The function below is the best attempt I've had. 下面的功能是我的最佳尝试。 I couldn't think of anything else except maybe create helper functions? 除了创建辅助函数外,我什么都没想到?

Code

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")

My results are correct and the function works as intended, but I feel like the code is messy and there is a better way to do this without getting really convoluted. 我的结果是正确的,并且该功能可以按预期工作,但是我感觉代码很杂乱,并且有一种更好的方法可以做到这一点而又不会令人费解。

First, you should create a parse_month function for better testing. 首先,您应该创建一个parse_month函数以进行更好的测试。 This parse_month function can have several internal parsers, one for each format: "int", datetime with "%b", datetime with "%B". parse_month函数可以具有多个内部解析器,每种内部解析器一种:“ int”,带有“%b”的datetime,带有“%B”的datetime。 This is implementation detail. 这是实现细节。

One way to do that could be: 一种方法是:

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)

Then, you can use this function to prompt the user: 然后,您可以使用此功能来提示用户:

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

If you don't want to reinvent the wheel, Arrow is your friend: 如果您不想重新发明轮子, 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM