Python 中是否有相当于 C# 的
DateTime.TryParse()
的功能?
我指的是它避免抛出异常的事实,而不是它猜测格式的事实。
如果你不想要异常,就捕获异常。
try:
d = datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
except ValueError:
d = None
在 Python 禅宗中,显式优于隐式。
strptime
always 返回以指定的确切格式解析的日期时间。这是有道理的,因为你必须定义失败时的行为,也许你真正想要的是。
except ValueError:
d = datetime.datetime.now()
或
except ValueError:
d = datetime.datetime.fromtimestamp(0)
或
except ValueError:
raise WebFramework.ServerError(404, "Invalid date")
通过明确说明,下一个阅读它的人可以清楚故障转移行为是什么,并且这就是您所需要的。
或者您确信该日期不会无效;它来自数据库 DATETIME 列,在这种情况下不会有异常需要捕获,所以不要捕获它。
我们希望
try...catch
多种日期时间格式 fmt1,fmt2,...,fmtn
并抑制/处理所有不匹配的异常(来自 strptime
)(特别是,避免需要令人讨厌的 n 深缩进梯子 try..catch
子句) 。我发现了两种优雅的方法,第二个通常是最好的。 (这对于现实世界的数据来说是一个大问题,其中多个、不匹配、不完整、不一致和多语言/区域日期格式通常在一个数据集中自由混合。)
1) 单独尝试应用每种格式并处理每个单独的
strptime()
失败作为 None
的返回值,因此您可以链接 fn 调用...
首先,改编自 @OrWeis' 的紧凑性答案:
def try_strptime_single_format(s, fmt):
try:
return datetime.datetime.strptime(s, fmt)
except ValueError:
return None
现在您可以调用为
try_strptime(s, fmt1) or try_strptime(s, fmt2) or 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
不是我们想要的 droid,因为它会在每个循环传递后执行,即在每个候选格式上执行,而不是在循环结束时执行一次。)
我发现实现 2) 更干净、更好。特别是,该函数/方法可以存储默认格式的列表,这使得它在实际数据上更加安全,并且更少出现异常。 (我们甚至可以根据其他列推断要应用哪些默认格式,例如,首先在德语数据上尝试德语日期格式,在阿拉伯语数据上尝试阿拉伯语,在博客数据上尝试网络日志日期时间格式等)
不,你要求的不是惯用的Python,因此通常不会有像标准库中那样丢弃错误的函数。 相关标准库模块记录如下:
http://docs.python.org/library/datetime.html
http://docs.python.org/library/time.html
解析函数都会在无效输入时引发异常。
但是,正如其他答案所述,为您的应用程序构建一个应用程序并不会非常困难(您的问题是“在Python中”而不是“在Python标准库中”,因此不清楚是否有助于编写这样的应用程序)函数“Python”是否回答了问题)。
这是一个等效的函数实现
import datetime
def try_strptime(s, format):
"""
@param s the string to parse
@param format the format to attempt parsing of the given string
@return the parsed datetime or None on failure to parse
@see datetime.datetime.strptime
"""
try:
date = datetime.datetime.strptime(s, format)
except ValueError:
date = None
return date
暴力也是一种选择:
def TryParse(datestring, offset):
nu = datetime.datetime.now()
retval = nu
formats = ["%d-%m-%Y","%Y-%m-%d","%d-%m-%y","%y-%m-%d"]
if datestring == None:
retval = datetime.datetime(nu.year,nu.month,nu.day,0,0,0) - datetime.timedelta(offset,0,0,0,0,0,0)
elif datestring == '':
retval = datetime.datetime(nu.year,nu.month,nu.day,0,0,0) - datetime.timedelta(offset,0,0,0,0,0,0)
else:
succes = False
for aformat in formats:
try:
retval = datetime.datetime.strptime(datestring,aformat)
succes = True
break
except:
pass
if not succes:
retval = datetime.datetime(nu.year,nu.month,nu.day,0,0,0) - datetime.timedelta(offset,0,0,0,0,0,0)
return retval
使用
time.strptime
解析字符串中的日期。
文档:http://docs.python.org/library/time.html#time.strptime
示例来自:http://pleac.sourceforge.net/pleac_python/datesandtimes.html
#-----------------------------
# Parsing Dates and Times from Strings
time.strptime("Tue Jun 16 20:18:03 1981")
# (1981, 6, 16, 20, 18, 3, 1, 167, -1)
time.strptime("16/6/1981", "%d/%m/%Y")
# (1981, 6, 16, 0, 0, 0, 1, 167, -1)
# strptime() can use any of the formatting codes from time.strftime()
# The easiest way to convert this to a datetime seems to be;
now = datetime.datetime(*time.strptime("16/6/1981", "%d/%m/%Y")[0:5])
# the '*' operator unpacks the tuple, producing the argument list.
我同意 tryparse 是 c# 上非常有用的函数。不幸的是,Python 中没有等效的直接函数(可能我不知道)。我相信您想检查字符串是否为日期而不用担心日期格式。我的建议是使用
pandas
to_datetime
功能:
def is_valid_date(str_to_validate: str) -> bool:
try:
if pd.to_datetime(str_to_validate):
return True
else:
return False
except ValueError:
return False
strptime 怎么样?
http://docs.python.org/library/time.html#time.strptime
如果无法根据提供的格式解析字符串,它将抛出 ValueError。
编辑:
因为在我回答问题后,问题被编辑以包含有关例外的部分。我想对此添加一条注释。
正如其他答案中所指出的,如果您不希望程序引发异常,您可以简单地捕获它并处理它:
try:
date = datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
except ValueError:
date = None
这是一种Python式的方式来做你想做的事。