[英]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? 除了创建辅助函数外,我什么都没想到?
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.