¿Cómo truncar la hora en un objeto DateTime en Python?


¿Cuál es una forma elegante de truncar un objeto datetime de python?

En este caso particular, al día. Así que básicamente establecer hora, minuto, segundos y microsegundos a 0.

Me gustaría que la salida también fuera un objeto datetime, no una cadena.

Author: Chris Stryczynski, 2011-03-29

12 answers

Creo que esto es lo que estás buscando...

>>> dt = datetime.datetime.now()
>>> dt = dt.replace(hour=0, minute=0, second=0, microsecond=0) # Returns a copy
>>> dt
datetime.datetime(2011, 3, 29, 0, 0)

Pero si realmente no te importa el aspecto temporal de las cosas, entonces realmente solo deberías estar pasando date objetos...

>>> d_truncated = datetime.date(dt.year, dt.month, dt.day)
>>> d_truncated
datetime.date(2011, 3, 29)
 268
Author: Chris W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-03 21:18:29

Use un date no un datetime si no le importa el tiempo.

>>> now = datetime.now()
>>> now.date()
datetime.date(2011, 3, 29)

Puede actualizar una fecha y hora como esta:

>>> now.replace(minute=0, hour=0, second=0, microsecond=0)
datetime.datetime(2011, 3, 29, 0, 0)
 40
Author: Jochen Ritzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-29 17:05:12

Cuatro años después: otro camino, evitando replace

Sé que la respuesta aceptada de hace cuatro años funciona, pero esto parece un poco más liviano que usar replace:

dt = datetime.date.today()
dt = datetime.datetime(dt.year, dt.month, dt.day)

Notas

  • Cuando se crea un objeto datetime sin pasar propiedades de tiempo al constructor, se obtiene midnight.
  • Como otros han señalado, esto supone que desea un objeto datetime para su uso posterior con timedeltas.
  • Puedes, por supuesto, sustituir esto por la primera línea: dt = datetime.datetime.now()
 19
Author: zx81,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-02 06:44:19

No se puede truncar un objeto datetime porque es inmutable.

Sin embargo, aquí hay una manera de construir una nueva datetime con campos de 0 horas, minutos, segundos y microsegundos, sin tirar la fecha original o tzinfo:

newdatetime = now.replace(hour=0, minute=0, second=0, microsecond=0)
 15
Author: ʇsәɹoɈ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-01 20:10:06

Para obtener una medianoche correspondiente a un objeto datetime dado, puede usar datetime.combine() método :

>>> from datetime import datetime, time
>>> dt = datetime.utcnow()
>>> dt.date()
datetime.date(2015, 2, 3)
>>> datetime.combine(dt, time.min)
datetime.datetime(2015, 2, 3, 0, 0)

La ventaja en comparación con el método .replace() es que la solución basada en datetime.combine() seguirá funcionando incluso si datetime el módulo introduce el soporte de nanosegundos .

tzinfo se puede conservar si es necesario, pero el desplazamiento utc puede ser diferente a medianoche, por ejemplo, debido a una transición DST y, por lo tanto, una solución ingenua (configuración del atributo tzinfo time) puede fallar. Ver ¿Cómo obtengo la hora UTC de "medianoche" para una zona horaria determinada?

 12
Author: jfs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:32

Puede usar datetime.strftime para extraer el día, el mes, el año...

Ejemplo:

from datetime import datetime
d = datetime.today()

# Retrieves the day and the year
print d.strftime("%d-%Y")

Salida (para hoy):

29-2011

Si solo desea recuperar el día, puede usar el atributo day como:

from datetime import datetime
d = datetime.today()

# Retrieves the day
print d.day

Ouput (por hoy):

29
 3
Author: Sandro Munda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-29 17:04:37

Podrías usar pandas para eso (aunque podría ser una sobrecarga para esa tarea). Podrías usar redondo, floor and ceil like for usual numbers and any pandas frequency from offset-alias :

import pandas as pd
import datetime as dt

now = dt.datetime.now()
pd_now = pd.Timestamp(now)

freq = '1d'
pd_round = pd_now.round(freq)
dt_round = pd_round.to_pydatetime()

print(now)
print(dt_round)

"""
2018-06-15 09:33:44.102292
2018-06-15 00:00:00
"""
 3
Author: Anton Protopopov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-15 12:08:51

Hay una gran biblioteca utilizada para manipular fechas: Delorean

import datetime
from delorean import Delorean
now = datetime.datetime.now()
d = Delorean(now, timezone='US/Pacific)

>>> now    
datetime.datetime(2015, 3, 26, 19, 46, 40, 525703)

>>> d.truncate('second')
Delorean(datetime=2015-03-26 19:46:40-07:00, timezone=US/Pacific)

>>> d.truncate('minute')
Delorean(datetime=2015-03-26 19:46:00-07:00, timezone=US/Pacific)

>>> d.truncate('hour')
Delorean(datetime=2015-03-26 19:00:00-07:00, timezone=US/Pacific)

>>> d.truncate('day')
Delorean(datetime=2015-03-26 00:00:00-07:00, timezone=US/Pacific)

>>> d.truncate('month')
Delorean(datetime=2015-03-01 00:00:00-07:00, timezone=US/Pacific)

>>> d.truncate('year')
Delorean(datetime=2015-01-01 00:00:00-07:00, timezone=US/Pacific)

Y si desea recuperar el valor datetime:

>>> d.truncate('year').datetime
datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)
 2
Author: DmitrySemenov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-27 02:54:50

Hay un módulo datetime_truncate que maneja esto para usted. Sólo llama datetime.reemplazar.

 1
Author: kyrre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-01 11:47:25

6 años después... Encontré este post y me gustó más el enfoque numpy:

import numpy as np
dates_array = np.array(['2013-01-01', '2013-01-15', '2013-01-30']).astype('datetime64[ns]')
truncated_dates = dates_array.astype('datetime64[D]')

Salud

 0
Author: Matias Thayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-25 10:47:21

Si está tratando con una Serie de tipo DateTime, hay una forma más eficiente de truncarlos, especialmente cuando el objeto Series tiene muchas filas.

Puede utilizar la función floor

Por ejemplo, si desea truncar a horas:

Generar un rango de fechas

times = pd.Series(pd.date_range(start='1/1/2018 04:00:00', end='1/1/2018 22:00:00', freq='s'))

Podemos comprobarlo comparando el tiempo de ejecución entre las funciones replace y floor.

%timeit times.apply(lambda x : x.replace(minute=0, second=0, microsecond=0))
>>> 341 ms ± 18.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit times.dt.floor('h')
>>>>2.26 ms ± 451 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
 0
Author: Abraham Simpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-19 00:10:01

¿Qué significa truncar?

Usted tiene control total sobre el formato usando el método strftime() y usando una cadena de formato apropiada.

Http://docs.python.org/library/datetime.html#strftime-strptime-behavior

 -1
Author: Andreas Jung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-29 16:54:17