Extrayendo fecha de una cadena en Python


82

¿Cómo puedo extraer la fecha de una cadena como "mono 2010-07-10 love banana"? ¡Gracias!


3
Solo una pista: comienza y termina con un dígito. Dejame pensar sobre eso. Aunque, regex puede ser tu amigo allí.
— Hamish Grubijan

Respuestas:


82

Si la fecha se da en una forma fija, simplemente puede usar una expresión regular para extraer la fecha y "datetime.datetime.strptime" para analizar la fecha:

import re
from datetime import datetime

match = re.search(r'\d{4}-\d{2}-\d{2}', text)
date = datetime.strptime(match.group(), '%Y-%m-%d').date()

De lo contrario, si la fecha se da de forma arbitraria, no podrá extraerla fácilmente.


1
¿Qué pasa si está en formato europeo, como 20/01/1980 que significa "20 de enero de 1980"? ¿Qué pasa si los meses / días / años quedan fuera del rango razonable?
— Hamish Grubijan

@lunaryorn En la primera declaración, ¿"re" se refiere a la cadena donde estamos buscando nuestro patrón deseado?
— vishal

@ vishal.k Se refiere a la incorporada en el remódulo, es decir, import re.
— lunaryorn

En caso de que alguien más cometiera el mismo error: necesita hacerlo en from datetime import datetimelugar deimport datetime
— dankal444

155

Usando python-dateutil :

In [1]: import dateutil.parser as dparser

In [18]: dparser.parse("monkey 2010-07-10 love banana",fuzzy=True)
Out[18]: datetime.datetime(2010, 7, 10, 0, 0)

Las fechas no válidas generan un ValueError:

In [19]: dparser.parse("monkey 2010-07-32 love banana",fuzzy=True)
# ValueError: day is out of range for month

Puede reconocer fechas en muchos formatos:

In [20]: dparser.parse("monkey 20/01/1980 love banana",fuzzy=True)
Out[20]: datetime.datetime(1980, 1, 20, 0, 0)

Tenga en cuenta que adivina si la fecha es ambigua:

In [23]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True)
Out[23]: datetime.datetime(1980, 10, 1, 0, 0)

Pero la forma en que analiza las fechas ambiguas es personalizable:

In [21]: dparser.parse("monkey 10/01/1980 love banana",fuzzy=True, dayfirst=True)
Out[21]: datetime.datetime(1980, 1, 10, 0, 0)

3
@Hamish: Si hay dos fechas (como en el caso de "monkey 10/01/1980 love 7/10/2010 banana"), puede generar un ValueError, o (como en el caso de "monkey 10/01/1980 love 2010-07-10 banana") puede malinterpretar la segunda fecha como indicando horas, minutos, segundos o zona horaria. fuzzy=Truele da licencia para adivinar.
— unutbu

1
@unutbu str = "Por flufie  · 14 de octubre de 2010 a las 11:22 pm  · 26 respuestas" Al usar dateutil obtengo "ValueError: la hora debe estar en 0..23"
— saravanan

¿Qué pasa si hay más de una fecha en el texto?
— alvas

1
@alvas: La parsefunción puede generar una excepción (incluso si fuzzy=True), o con fuzzy=True, puede devolver la primera fecha o una mezcla compuesta por partes de ambas fechas. Entonces, en realidad, parsesolo debería llamarse en una cadena que contenga una fecha.
— unutbu

1
@Kailegh: Sí, sería posible deducir los índices usando fuzzy_with_tokens = True . Si desea más aclaraciones, inicie una nueva pregunta.
— unutbu

27

Para extraer la fecha de una cadena en Python; el mejor módulo disponible es el módulo de buscador de fechas .

Puede usarlo en su proyecto de Python siguiendo los sencillos pasos que se indican a continuación.

Paso 1: Instale el paquete datefinder

pip install datefinder

Paso 2: Úselo en su proyecto

import datefinder

input_string = "monkey 2010-07-10 love banana"
# a generator will be returned by the datefinder module. I'm typecasting it to a list. Please read the note of caution provided at the bottom.
matches = list(datefinder.find_dates(input_string))

if len(matches) > 0:
    # date returned will be a datetime.datetime object. here we are only using the first match.
    date = matches[0]
    print date
else:
    print 'No dates found'

nota: si espera una gran cantidad de coincidencias; entonces, el encasillado a la lista no será una forma recomendada, ya que tendrá una gran sobrecarga de rendimiento.


1
Descubrí que la datefindercoincidencia de fechas ambiguas es mejor que python-dateutildevolver solo dos fechas posibles de una publicación de blog de medium.com al azar en lugar de cinco. No estoy seguro de cómo se maneja diferentes lugares, sin embargo ...
— CpILL

Esto es bastante bueno, excepto que de alguna manera no funciona cuando hay dos puntos (:) antes de la cadena de fecha: string = "Assessment Date: 17-May-2017 at 13:31" list(datefinder.find_dates(string.lower())) #[] string = "Assessment Date 17-May-2017 at 13:31" list(datefinder.find_dates(string.lower())) #[datetime.datetime(2017, 5, 17, 13, 31)]
— Narahari BM

Estoy de acuerdo en que el buscador de fechas es mucho mejor que el analizador de fechas para texto ambiguo
— Jay Jung

2

Con Pygrok, puede definir extensiones abstractas para la sintaxis de expresiones regulares.

Los patrones personalizados se pueden incluir en su expresión regular en el formato %{PATTERN_NAME}.

También puede crear una etiqueta para ese patrón, separando con dos puntos: %s{PATTERN_NAME:matched_string}. Si el patrón coincide, el valor se devolverá como parte del diccionario resultante (p. Ej.result.get('matched_string') . )

Por ejemplo:

from pygrok import Grok

input_string = 'monkey 2010-07-10 love banana'
date_pattern = '%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day}'

grok = Grok(date_pattern)
print(grok.match(input_string))

El valor resultante será un diccionario:

{'month': '07', 'day': '10', 'year': '2010'}

Si date_pattern no existe en input_string, el valor de retorno será None. Por el contrario, si su patrón no tiene etiquetas, devolverá un diccionario vacío{}

Referencias:


Esta biblioteca es muy Python 2
— Walter hace

1

También puede probar el módulo dateparser , que puede ser más lento que el datefinder en texto libre, pero que debería cubrir más casos y formatos de fecha potenciales, así como una cantidad significativa de idiomas.


-5

Si conoce la posición del objeto de fecha en la cadena (por ejemplo, en un archivo de registro), puede usar .split () [índice] para extraer la fecha sin conocer completamente el formato.

Por ejemplo:

>>> string = 'monkey 2010-07-10 love banana'
>>> date = string.split()[1]
>>> date
'2010-07-10'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.