Python有没有相当于C#中DateTime.TryParse()的方法?
在Python中有没有类似于C#的 DateTime.TryParse()
这样的功能呢?
我指的是它可以避免抛出错误,而不是说它能猜测日期格式。
8 个回答
不,你问的这个问题在Python中并不是常见的写法,所以标准库里一般不会有那种直接忽略错误的函数。相关的标准库模块可以在这里找到:
http://docs.python.org/library/datetime.html
http://docs.python.org/library/time.html
所有的解析函数在输入不合法时都会抛出错误。
不过,正如其他回答所说,为你的应用程序构建一个这样的函数并不是特别困难(你问的问题是“在Python中”而不是“在Python标准库中”,所以不太清楚帮助你写这样一个“在Python中”的函数是否算是回答了你的问题)。
我们想要尝试多种日期时间格式 fmt1, fmt2,...,fmtn
,并处理那些不匹配的错误(这些错误来自 strptime
),特别是希望避免使用一大堆嵌套的 try..catch
语句。这个问题在现实数据中很常见,因为数据集中常常会混合多种不匹配、不完整、不一致以及多语言/地区的日期格式。
1) 单独尝试每种格式,并将每次 strptime()
失败处理为返回值 None
,这样你可以链式调用函数...
首先,从 @OrWeis 的答案中简化一下:
def try_strptime_single_format(s, fmt):
try:
return datetime.datetime.strptime(s, fmt)
except ValueError:
return None
现在你可以像这样调用 try_strptime(s, fmt1) 或 try_strptime(s, fmt2) 或 try_strptime(s, fmt3) ...
但是我们可以进一步改进:
2) 应用多种可能的格式(可以作为参数传入或使用合理的默认值),遍历这些格式,内部捕获并处理任何错误:
更简洁、更简单且更面向对象的做法是将 formats
参数设置为单个字符串或列表,然后遍历这个列表...这样你的调用就简化为 try_strptime(s, [fmt1, fmt2, fmt3, ...])
def try_strptime(s, fmts=['%d-%b-%y','%m/%d/%Y']):
for fmt in fmts:
try:
return datetime.strptime(s, fmt)
except:
continue
return None # or reraise the ValueError if no format matched, if you prefer
(顺便提一下,...finally
不是我们想要的,因为它会在每次循环后执行,也就是说在每个候选格式上执行,而不是在循环结束时执行一次。)
我发现第二种实现方式更简洁、更好。特别是这个函数/方法可以存储一个默认格式的列表,这样在处理现实数据时更安全,也不容易出现异常。(我们甚至可以根据其他列推断出应该使用哪些默认格式,比如在德语数据上优先尝试德语日期格式,在阿拉伯语数据上尝试阿拉伯格式,在网页日志数据上使用网页日志的日期时间格式等等。)
如果你不想遇到错误,那就去处理这个错误。
try:
d = datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
except ValueError:
d = None
在Python的哲学中,明确的比隐含的要好。strptime
总是返回一个按照你指定的格式解析的日期时间。这是有道理的,因为你需要定义在失败时该怎么处理,也许你真正想要的是这样的行为。
except ValueError:
d = datetime.datetime.now()
或者
except ValueError:
d = datetime.datetime.fromtimestamp(0)
或者
except ValueError:
raise WebFramework.ServerError(404, "Invalid date")
通过明确地说明,下一位阅读代码的人就能清楚地知道在出错时应该怎么处理,这样的处理方式也是你所需要的。
或者你可能很确定日期不会无效;比如它来自数据库的DATETIME列,这种情况下就不会有错误需要处理,所以就不需要去捕捉它。