Convertir cadena en fecha y hora

Corto y sencillo. Tengo una gran lista de fechas y fechas como estas:

Jun 1 2005 1:33PM Aug 28 1999 12:00AM 

Voy a volver a colocarlos en campos de fecha y hora adecuados en una base de datos, así que necesito hacerles magia en objetos de fecha y hora reales.

Cualquier ayuda (incluso si es solo una patada en la dirección correcta) sería apreciada.

Edición: Esto está pasando por el ORM de Django, por lo que no puedo usar SQL para hacer la conversión al insertar.

datetime.strptime es la rutina principal para analizar cadenas en tiempos de datos. Puede manejar todo tipo de formatos, con el formato determinado por una cadena de formato que le des:

 from datetime import datetime datetime_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') 

El objeto datetime resultante es timezone-naive.

Campo de golf:

  • Documentación de Python para strptime : Python 2 , Python 3

  • Documentación de Python para cadenas de formato strptime / strftime : Python 2 , Python 3

  • strftime.org es también una muy buena referencia para strftime

Notas:

  • strptime = “tiempo de análisis de cadena”
  • strftime = “tiempo de formato de cadena”
  • Pronuncialo en voz alta hoy y no tendrás que buscarlo nuevamente en 6 meses.

Utilice la biblioteca de citas de terceros:

 from dateutil import parser dt = parser.parse("Aug 28 1999 12:00AM") 

Puede manejar la mayoría de los formatos de fecha, incluido el que necesita analizar. Es más conveniente que strptime, ya que puede adivinar el formato correcto la mayor parte del tiempo.

Es muy útil para escribir pruebas, donde la legibilidad es más importante que el rendimiento.

Puedes instalarlo con:

 pip install python-dateutil 

Echa un vistazo a strptime en el módulo de tiempo . Es lo inverso de strftime .

 $ python >>> import time >>> time.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') time.struct_time(tm_year=2005, tm_mon=6, tm_mday=1, tm_hour=13, tm_min=33, tm_sec=0, tm_wday=2, tm_yday=152, tm_isdst=-1) 

He reunido un proyecto que puede convertir algunas expresiones realmente limpias. Echa un vistazo a timestring .

Aquí hay algunos ejemplos a continuación:

pip install timestring

 >>> import timestring >>> timestring.Date('monday, aug 15th 2015 at 8:40 pm')  >>> timestring.Date('monday, aug 15th 2015 at 8:40 pm').date datetime.datetime(2015, 8, 15, 20, 40) >>> timestring.Range('next week')  >>> (timestring.Range('next week').start.date, timestring.Range('next week').end.date) (datetime.datetime(2014, 3, 10, 0, 0), datetime.datetime(2014, 3, 14, 0, 0)) 

Recuerda esto y no necesitas volver a confundirte en la conversión de fecha y hora.

Cadena al objeto datetime = strptime

Objeto datetime a otros formatos = strftime

Jun 1 2005 1:33PM

es igual a

%b %d %Y %I:%M%p

% b mes como nombre abreviado de la localidad (junio)

% d Día del mes como un número decimal con cero (1)

% Y Año con siglo como número decimal (2015)

% I hora (reloj de 12 horas) como un número decimal sin relleno (01)

% M minuto como un número decimal con cero (33)

El equivalente de% p Locale de AM o PM (PM)

por lo que necesita strptime es decir, convertir la string

 >>> dates = [] >>> dates.append('Jun 1 2005 1:33PM') >>> dates.append('Aug 28 1999 12:00AM') >>> from datetime import datetime >>> for d in dates: ... date = datetime.strptime(d, '%b %d %Y %I:%M%p') ... print type(date) ... print date ... 

Salida

  2005-06-01 13:33:00  1999-08-28 00:00:00 

¿Qué pasa si tienes un formato diferente de fechas puedes usar panda o dateutil.parse?

 >>> import dateutil >>> dates = [] >>> dates.append('12 1 2017') >>> dates.append('1 1 2017') >>> dates.append('1 12 2017') >>> dates.append('June 1 2017 1:30:00AM') >>> [parser.parse(x) for x in dates] 

Salida

 [datetime.datetime(2017, 12, 1, 0, 0), datetime.datetime(2017, 1, 1, 0, 0), datetime.datetime(2017, 1, 12, 0, 0), datetime.datetime(2017, 6, 1, 1, 30)] 

Muchas marcas de tiempo tienen una zona horaria implícita. Para asegurarse de que su código funcione en cada zona horaria, debe usar UTC internamente y adjuntar una zona horaria cada vez que un objeto extraño ingrese al sistema.

Python 3.2+:

 >>> datetime.datetime.strptime( ... "March 5, 2014, 20:13:50", "%B %d, %Y, %H:%M:%S" ... ).replace(tzinfo=datetime.timezone(datetime.timedelta(hours=-3))) 

Algo que no se menciona aquí y es útil: agregar un sufijo al día. Desacoplé la lógica del sufijo para que pueda usarlo para cualquier número que desee, no solo fechas.

 import time def num_suffix(n): ''' Returns the suffix for any given int ''' suf = ('th','st', 'nd', 'rd') n = abs(n) # wise guy tens = int(str(n)[-2:]) units = n % 10 if tens > 10 and tens < 20: return suf[0] # teens with 'th' elif units <= 3: return suf[units] else: return suf[0] # 'th' def day_suffix(t): ''' Returns the suffix of the given struct_time day ''' return num_suffix(t.tm_mday) # Examples print num_suffix(123) print num_suffix(3431) print num_suffix(1234) print '' print day_suffix(time.strptime("1 Dec 00", "%d %b %y")) print day_suffix(time.strptime("2 Nov 01", "%d %b %y")) print day_suffix(time.strptime("3 Oct 02", "%d %b %y")) print day_suffix(time.strptime("4 Sep 03", "%d %b %y")) print day_suffix(time.strptime("13 Nov 90", "%d %b %y")) print day_suffix(time.strptime("14 Oct 10", "%d %b %y"))​​​​​​​ 

Aquí hay dos soluciones que usan Pandas para convertir fechas formateadas como cadenas en objetos datetime.date.

 import pandas as pd dates = ['2015-12-25', '2015-12-26'] # 1) Use a list comprehension. >>> [d.date() for d in pd.to_datetime(dates)] [datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)] # 2) Convert the dates to a DatetimeIndex and extract the python dates. >>> pd.DatetimeIndex(dates).date.tolist() [datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)] 

Tiempos

 dates = pd.DatetimeIndex(start='2000-1-1', end='2010-1-1', freq='d').date.tolist() >>> %timeit [d.date() for d in pd.to_datetime(dates)] # 100 loops, best of 3: 3.11 ms per loop >>> %timeit pd.DatetimeIndex(dates).date.tolist() # 100 loops, best of 3: 6.85 ms per loop 

Y aquí es cómo convertir los ejemplos de fecha y hora originales del OP:

 datetimes = ['Jun 1 2005 1:33PM', 'Aug 28 1999 12:00AM'] >>> pd.to_datetime(datetimes).to_pydatetime().tolist() [datetime.datetime(2005, 6, 1, 13, 33), datetime.datetime(1999, 8, 28, 0, 0)] 

Hay muchas opciones para convertir de cadenas a to_datetime tiempo de Pandas usando to_datetime , así que verifique los documentos si necesita algo especial.

Del mismo modo, las marcas de tiempo tienen muchas propiedades y métodos a los que se puede acceder además de .date

Personalmente, me gusta la solución utilizando el módulo de parser , que es la segunda respuesta a esta pregunta y es hermosa, ya que no tienes que construir literales de cadena para que funcione. PERO , un inconveniente es que es 90% más lento que la respuesta aceptada con strptime respuesta.

 from dateutil import parser from datetime import datetime import timeit def dt(): dt = parser.parse("Jun 1 2005 1:33PM") def strptime(): datetime_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') print(timeit.timeit(stmt=dt, number=10**5)) print(timeit.timeit(stmt=strptime, number=10**5)) >10.70296801342902 >1.3627995655316933 

Mientras no haga esto un millón de veces una y otra vez, sigo pensando que el método del parser es más conveniente y manejará la mayoría de los formatos de tiempo automáticamente.

Ejemplo de objeto de fecha y hora Django Timezone.

 import datetime from django.utils.timezone import get_current_timezone tz = get_current_timezone() format = '%b %d %Y %I:%M%p' date_object = datetime.datetime.strptime('Jun 1 2005 1:33PM', format) date_obj = tz.localize(date_object) 

Esta conversión es muy importante para Django y Python cuando tienes USE_TZ = True :

 RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2016-03-04 00:00:00) while time zone support is active. 
 In [34]: import datetime In [35]: _now = datetime.datetime.now() In [36]: _now Out[36]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000) In [37]: print _now 2016-01-19 09:47:00.432000 In [38]: _parsed = datetime.datetime.strptime(str(_now),"%Y-%m-%d %H:%M:%S.%f") In [39]: _parsed Out[39]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000) In [40]: assert _now == _parsed 

para el formato unix / mysql 2018-10-15 20:59:29

 from datetime import datetime datetime_object = datetime.strptime('2018-10-15 20:59:29', '%Y-%m-%d %H:%M:%S') 

Crea una pequeña función de utilidad como:

 def date(datestr="", format="%Y-%m-%d"): from datetime import datetime if not datestr: return datetime.today().date() return datetime.strptime(datestr, format).date() 

Esto es lo suficientemente versátil:

  • Si no pasa ningún argumento volverá la fecha de hoy.
  • Hay un formato de fecha como predeterminado que puede anular.
  • Puede modificarlo fácilmente para devolver un datetime.

El módulo de fecha y hora de Python es bueno para obtener los formatos de fecha y hora de fecha.

 import datetime new_date_format1 = datetime.datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') new_date_format2 = datetime.datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p').strftime('%Y/%m/%d %I:%M%p') print new_date_format1 print new_date_format2 

Salida:

 2005-06-01 13:33:00 2005/06/01 01:33PM 

En Python> = 3.7.0,

para convertir la cadena YYYY-MM-DD en un objeto datetime.fromisoformat , se podría usar datetime.fromisoformat .

 >>> from datetime import datetime >>> date_string = "2012-12-12 10:10:10" >>> print (datetime.fromisoformat(date_string)) >>> 2012-12-12 10:10:10 

La flecha ofrece muchas funciones útiles para fechas y horas. Este bit de código proporciona una respuesta a la pregunta y muestra que la flecha también es capaz de formatear fechas fácilmente y mostrar información de otras configuraciones regionales.

 >>> import arrow >>> dateStrings = [ 'Jun 1 2005 1:33PM', 'Aug 28 1999 12:00AM' ] >>> for dateString in dateStrings: ... dateString ... arrow.get(dateString.replace(' ',' '), 'MMM D YYYY H:mmA').datetime ... arrow.get(dateString.replace(' ',' '), 'MMM D YYYY H:mmA').format('ddd, Do MMM YYYY HH:mm') ... arrow.get(dateString.replace(' ',' '), 'MMM D YYYY H:mmA').humanize(locale='de') ... 'Jun 1 2005 1:33PM' datetime.datetime(2005, 6, 1, 13, 33, tzinfo=tzutc()) 'Wed, 1st Jun 2005 13:33' 'vor 11 Jahren' 'Aug 28 1999 12:00AM' datetime.datetime(1999, 8, 28, 0, 0, tzinfo=tzutc()) 'Sat, 28th Aug 1999 00:00' 'vor 17 Jahren' 

Consulte http://arrow.readthedocs.io/en/latest/ para obtener más información.

Puedes usar easy_date para hacerlo más fácil:

 import date_converter converted_date = date_converter.string_to_datetime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p') 

Si solo desea el formato de fecha, puede convertirlo manualmente pasando sus campos individuales como:

 >>> import datetime >>> date = datetime.date(int('2017'),int('12'),int('21')) >>> date datetime.date(2017, 12, 21) >>> type(date)  

Puede pasar sus valores de cadena dividida para convertirlos en un tipo de fecha como:

 selected_month_rec = '2017-09-01' date_formate = datetime.date(int(selected_month_rec.split('-')[0]),int(selected_month_rec.split('-')[1]),int(selected_month_rec.split('-')[2])) 

Obtendrá el valor resultante en formato de fecha.

Sería útil para convertir la cadena a datetime y también con la zona horaria

 def convert_string_to_time(date_string, timezone): from datetime import datetime import pytz date_time_obj = datetime.strptime(date_string[:26], '%Y-%m-%d %H:%M:%S.%f') date_time_obj_timezone = pytz.timezone(timezone).localize(date_time_obj) return date_time_obj_timezone date = '2018-08-14 13:09:24.543953+00:00' TIME_ZONE = 'UTC' date_time_obj_timezone = convert_string_to_time(date, TIME_ZONE) 
 emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv") emp.info() 

muestra la columna “Fecha y hora de inicio” y “Última hora de inicio de sesión”, ambas son “objeto = cadenas” en el dataframe

  RangeIndex: 1000 entries, 0 to 999 Data columns (total 8 columns): First Name 933 non-null object Gender 855 non-null object 
 Start Date 1000 non-null object Last Login Time 1000 non-null object 
 Salary 1000 non-null int64 Bonus % 1000 non-null float64 Senior Management 933 non-null object Team 957 non-null object dtypes: float64(1), int64(1), object(6) memory usage: 62.6+ KB 

Al utilizar la opción parse_dates en la mención read_csv , puede convertir la cadena datetime en el formato read_csv datetime.

 emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv", parse_dates=["Start Date", "Last Login Time"]) emp.info()  RangeIndex: 1000 entries, 0 to 999 Data columns (total 8 columns): First Name 933 non-null object Gender 855 non-null object 
 Start Date 1000 non-null datetime64[ns] Last Login Time 1000 non-null datetime64[ns] 
 Salary 1000 non-null int64 Bonus % 1000 non-null float64 Senior Management 933 non-null object Team 957 non-null object dtypes: datetime64[ns](2), float64(1), int64(1), object(4) memory usage: 62.6+ KB 

También puedes usar el patito de facebook.

Pruébelo en línea aquí: https://duckling.wit.ai/

Hay una envoltura de python para la biblioteca: pip install duckling

Soporta mucho más que solo analizar el tiempo.

Mira mi respuesta

En los datos del mundo real, este es un problema real: formatos de fecha múltiples, no coincidentes, incompletos, inconsistentes y multilenguaje / región, que a menudo se mezclan libremente en un conjunto de datos. No está bien que el código de producción falle, y mucho menos que salga feliz como un zorro.

Necesitamos probar … capturar múltiples formatos de fecha y hora fmt1, fmt2, …, fmtn y suprimir / manejar las excepciones (de strptime() ) para todos aquellos que no coincidan (y en particular, evitar la necesidad de una sangría profunda yukky n Escalera de intencion … cláusulas de captura). De mi solucion

 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