Pregunta Convirtiendo cadena en datetime


Corto y simple. Tengo una gran lista de fechas como esta como cadenas:

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

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

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

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


1458
2018-01-21 18:00


origen


Respuestas:


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

from datetime import datetime

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

La resultante datetime el objeto es ingenuo en la zona horaria.

Campo de golf:

Notas:

  • strptime = "tiempo de análisis de cadenas"
  • strftime = "tiempo de formato de cadena"
  • Pronúncialo en voz alta hoy y no tendrás que volver a buscarlo en 6 meses.

2396
2018-01-21 18:08



Usa el tercero dateutil biblioteca:

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

623
2018-01-22 18:27



Revisa estriptís en el hora módulo. Es el inverso de tiempo de trabajo.

$ 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)

460
2018-01-21 18:07



He creado un proyecto que puede convertir algunas expresiones realmente ordenadas. Revisa cadena de tiempo.

Aquí hay algunos ejemplos a continuación:

pip install timestring
>>> import timestring
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm')
<timestring.Date 2015-08-15 20:40:00 4491909392>
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm').date
datetime.datetime(2015, 8, 15, 20, 40)
>>> timestring.Range('next week')
<timestring.Range From 03/10/14 00:00:00 to 03/03/14 00:00:00 4496004880>
>>> (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))

87
2018-03-02 14:22



Recuerde esto y no necesita confundirse nuevamente en la conversión de fecha y hora.

String to datetime object = strptime

objeto datetime a otros formatos = strftime

Jun 1 2005 1:33PM

es igual a

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

% b Month como nombre abreviado de la configuración regional (jun)

% d Día del mes como número decimal sin relleno (1)

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

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

% M Minuto como número decimal sin relleno (33)

% p Equivalente local de AM o PM (PM)

por lo que necesita convertir I-e strptime string a

>>> 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

<type 'datetime.datetime'>
2005-06-01 13:33:00
<type 'datetime.datetime'>
1999-08-28 00:00:00

¿Qué sucede si tiene un formato diferente de fechas que puede 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)]

33
2017-12-10 13:00



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)))

30
2018-03-06 11:53



Algo que no se menciona aquí y es útil: agregar un sufijo al día. Desacopliqué la lógica del sufijo para que pueda usarla para cualquier número que desee, no solo las 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"))​​​​​​​

21
2017-10-14 00:13



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í está cómo convertir los ejemplos de fecha y hora originales de 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 las cadenas a Pandas Timestamps usando to_datetime, así que revisa documentos si necesitas algo especial.

Del mismo modo, Timestamps tienen muchos propiedades y métodos a la que se puede acceder además de .date


19
2017-12-20 03:03



Ejemplo de objeto datetime de Django Timezone aware.

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.

12
2017-11-20 17:58



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

11
2018-01-19 07:48