Comment vérifier si une chaîne peut être analysée à une date?
Ce sont toutes des dates valides. S'il y a un problème concernant le manque d'espace entre les éléments de l'élément n ° 3 et le dernier élément ci-dessus, cela peut être facilement résolu en insérant automatiquement un espace entre les lettres/caractères et les chiffres, si nécessaire.
Mais d'abord, les bases:
J'ai essayé de le mettre dans un if statement
:
if datetime.strptime(item, '%Y') or datetime.strptime(item, '%b %d %y') or datetime.strptime(item, '%b %d %Y') or datetime.strptime(item, '%B %d %y') or datetime.strptime(item, '%B %d %Y'):
Mais c'est dans un bloc try-except et continue de renvoyer quelque chose comme ceci:
16343 time data 'JUNE1890' does not match format '%Y'
Sauf s'il remplit la première condition de l'instruction if
.
Pour clarifier, je n'ai pas réellement besoin de la valeur de la date - je veux juste savoir si elle l'est. Idéalement, cela aurait été quelque chose comme ceci:
if item is date:
print date
else:
print "Not a date"
Est-ce qu'il y a un moyen de faire ça?
La fonction parse
dans dateutils.parser
est capable d'analyser de nombreux formats de chaîne de date dans un objet datetime
.
Si vous voulez simplement savoir si une chaîne particulière pourrait représenter ou contenir une date valide, vous pouvez essayer la fonction simple suivante:
from dateutil.parser import parse
def is_date(string, fuzzy=False):
"""
Return whether the string can be interpreted as a date.
:param string: str, string to check for date
:param fuzzy: bool, ignore unknown tokens in string if True
"""
try:
parse(string, fuzzy=fuzzy)
return True
except ValueError:
return False
Vous avez alors:
>>> is_date("1990-12-1")
True
>>> is_date("2005/3")
True
>>> is_date("Jan 19, 1990")
True
>>> is_date("today is 2019-03-27")
False
>>> is_date("today is 2019-03-27", fuzzy=True)
True
>>> is_date("Monday at 12:01am")
True
>>> is_date("xyz_not_a_date")
False
>>> is_date("yesterday")
False
parse
peut reconnaître certaines chaînes comme des dates que vous ne voulez pas traiter comme des dates. Par exemple:
L'analyse de "12"
Et "1999"
Renverra un objet datetime représentant la date actuelle avec le jour et l'année substitués au nombre dans la chaîne
"23, 4"
Et "23 4"
Seront analysés comme datetime.datetime(2023, 4, 16, 0, 0)
.
"Friday"
Renverra la date du vendredi le plus proche à l'avenir."August"
Correspond à la date actuelle avec le mois changé en août.De plus, parse
n'est pas sensible aux paramètres régionaux, donc ne reconnaît pas les mois ou les jours de la semaine dans des langues autres que l'anglais.
Ces deux problèmes peuvent être résolus dans une certaine mesure en utilisant une classe parserinfo
personnalisée, qui définit la façon dont les noms de mois et de jour sont reconnus:
from dateutil.parser import parserinfo
class CustomParserInfo(parserinfo):
# three months in Spanish for illustration
MONTHS = [("Enero", "Enero"), ("Feb", "Febrero"), ("Marzo", "Marzo")]
Une instance de cette classe peut ensuite être utilisée avec parse
:
>>> parse("Enero 1990")
# ValueError: Unknown string format
>>> parse("Enero 1990", parserinfo=CustomParserInfo())
datetime.datetime(1990, 1, 27, 0, 0)
Si vous souhaitez analyser ces formats particuliers, vous pouvez simplement les comparer à une liste de formats:
txt='''\
Jan 19, 1990
January 19, 1990
Jan 19,1990
01/19/1990
01/19/90
1990
Jan 1990
January1990'''
import datetime as dt
fmts = ('%Y','%b %d, %Y','%b %d, %Y','%B %d, %Y','%B %d %Y','%m/%d/%Y','%m/%d/%y','%b %Y','%B%Y','%b %d,%Y')
parsed=[]
for e in txt.splitlines():
for fmt in fmts:
try:
t = dt.datetime.strptime(e, fmt)
parsed.append((e, fmt, t))
break
except ValueError as err:
pass
# check that all the cases are handled
success={t[0] for t in parsed}
for e in txt.splitlines():
if e not in success:
print e
for t in parsed:
print '"{:20}" => "{:20}" => {}'.format(*t)
Tirages:
"Jan 19, 1990 " => "%b %d, %Y " => 1990-01-19 00:00:00
"January 19, 1990 " => "%B %d, %Y " => 1990-01-19 00:00:00
"Jan 19,1990 " => "%b %d,%Y " => 1990-01-19 00:00:00
"01/19/1990 " => "%m/%d/%Y " => 1990-01-19 00:00:00
"01/19/90 " => "%m/%d/%y " => 1990-01-19 00:00:00
"1990 " => "%Y " => 1990-01-01 00:00:00
"Jan 1990 " => "%b %Y " => 1990-01-01 00:00:00
"January1990 " => "%B%Y " => 1990-01-01 00:00:00