¿Cómo incrementar una fecha y hora en un día?

152

¿Cómo incrementar el día de una fecha y hora?

for i in range(1, 35)
    date = datetime.datetime(2003, 8, i)
    print(date)

¿Pero necesito pasar meses y años correctamente? ¿Algunas ideas?

Pol
fuente

Respuestas:

60

Las fechas de incremento se pueden lograr usando objetos timedelta:

import datetime

datetime.datetime.now() + datetime.timedelta(days=1)

Busque objetos timedelta en los documentos de Python: http://docs.python.org/library/datetime.html

Piotr Duda
fuente
12

Aquí hay otro método para agregar días en la fecha usando la relación relativa de dateutil.

from datetime import datetime
from dateutil.relativedelta import relativedelta

print 'Today: ',datetime.now().strftime('%d/%m/%Y %H:%M:%S') 
date_after_month = datetime.now()+ relativedelta(day=1)
print 'After a Days:', date_after_month.strftime('%d/%m/%Y %H:%M:%S')

Salida:

Hoy: 25/06/2015 20:41:44

Después de un día: 01/06/2015 20:41:44

Atul Arvind
fuente
1
¿por qué lo timedelta()usarías en lugar de stdlib?
jfs
2
@JFSebastian Solo para compartir otra posible forma de agregar el día.
Atul Arvind
1
Si no hay ventaja, no creo que agregue valor.
Tejas Manohar
10

Todas las respuestas actuales son incorrectas en algunos casos, ya que no consideran que las zonas horarias cambien su desplazamiento en relación con UTC. Entonces, en algunos casos, agregar 24h es diferente de agregar un día calendario.

Solución propuesta

La siguiente solución funciona para Samoa y mantiene constante la hora local.

def add_day(today):
    """
    Add a day to the current day.

    This takes care of historic offset changes and DST.

    Parameters
    ----------
    today : timezone-aware datetime object

    Returns
    -------
    tomorrow : timezone-aware datetime object
    """
    today_utc = today.astimezone(datetime.timezone.utc)
    tz = today.tzinfo
    tomorrow_utc = today_utc + datetime.timedelta(days=1)
    tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
    tomorrow_utc_tz = tomorrow_utc_tz.replace(hour=today.hour,
                                              minute=today.minute,
                                              second=today.second)
    return tomorrow_utc_tz

Código probado

# core modules
import datetime

# 3rd party modules
import pytz


# add_day methods
def add_day(today):
    """
    Add a day to the current day.

    This takes care of historic offset changes and DST.

    Parameters
    ----------
    today : timezone-aware datetime object

    Returns
    -------
    tomorrow : timezone-aware datetime object
    """
    today_utc = today.astimezone(datetime.timezone.utc)
    tz = today.tzinfo
    tomorrow_utc = today_utc + datetime.timedelta(days=1)
    tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
    tomorrow_utc_tz = tomorrow_utc_tz.replace(hour=today.hour,
                                              minute=today.minute,
                                              second=today.second)
    return tomorrow_utc_tz


def add_day_datetime_timedelta_conversion(today):
    # Correct for Samoa, but dst shift
    today_utc = today.astimezone(datetime.timezone.utc)
    tz = today.tzinfo
    tomorrow_utc = today_utc + datetime.timedelta(days=1)
    tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
    return tomorrow_utc_tz


def add_day_dateutil_relativedelta(today):
    # WRONG!
    from dateutil.relativedelta import relativedelta
    return today + relativedelta(days=1)


def add_day_datetime_timedelta(today):
    # WRONG!
    return today + datetime.timedelta(days=1)


# Test cases
def test_samoa(add_day):
    """
    Test if add_day properly increases the calendar day for Samoa.

    Due to economic considerations, Samoa went from 2011-12-30 10:00-11:00
    to 2011-12-30 10:00+13:00. Hence the country skipped 2011-12-30 in its
    local time.

    See https://stackoverflow.com/q/52084423/562769

    A common wrong result here is 2011-12-30T23:59:00-10:00. This date never
    happened in Samoa.
    """
    tz = pytz.timezone('Pacific/Apia')
    today_utc = datetime.datetime(2011, 12, 30, 9, 59,
                                  tzinfo=datetime.timezone.utc)
    today_tz = today_utc.astimezone(tz)  # 2011-12-29T23:59:00-10:00
    tomorrow = add_day(today_tz)
    return tomorrow.isoformat() == '2011-12-31T23:59:00+14:00'


def test_dst(add_day):
    """Test if add_day properly increases the calendar day if DST happens."""
    tz = pytz.timezone('Europe/Berlin')
    today_utc = datetime.datetime(2018, 3, 25, 0, 59,
                                  tzinfo=datetime.timezone.utc)
    today_tz = today_utc.astimezone(tz)  # 2018-03-25T01:59:00+01:00
    tomorrow = add_day(today_tz)
    return tomorrow.isoformat() == '2018-03-26T01:59:00+02:00'


to_test = [(add_day_dateutil_relativedelta, 'relativedelta'),
           (add_day_datetime_timedelta, 'timedelta'),
           (add_day_datetime_timedelta_conversion, 'timedelta+conversion'),
           (add_day, 'timedelta+conversion+dst')]
print('{:<25}: {:>5} {:>5}'.format('Method', 'Samoa', 'DST'))
for method, name in to_test:
    print('{:<25}: {:>5} {:>5}'
          .format(name,
                  test_samoa(method),
                  test_dst(method)))

Resultados de la prueba

Method                   : Samoa   DST
relativedelta            :     0     0
timedelta                :     0     0
timedelta+conversion     :     1     0
timedelta+conversion+dst :     1     1
Martin Thoma
fuente
Las otras respuestas no son del todo incorrectas, están perfectamente bien mientras se trabaja con UTC o ingenua ( tzinfo == None) fecha y hora.
Delgan
3

Esta fue una solución sencilla para mí:

from datetime import timedelta, datetime

today = datetime.today().strftime("%Y-%m-%d")
tomorrow = datetime.today() + timedelta(1)
Aus_10
fuente
0

También puede importar timedelta para que el código sea más limpio.

from datetime import datetime, timedelta
date = datetime.now() + timedelta(seconds=[delta_value])

Luego convertir a fecha a cadena

date = date.strftime('%Y-%m-%d %H:%M:%S')

Python one liner es

date = (datetime.now() + timedelta(seconds=[delta_value])).strftime('%Y-%m-%d %H:%M:%S')
Roy
fuente
-2

Una solución corta sin bibliotecas en absoluto. :)

d = "8/16/18"
day_value = d[(d.find('/')+1):d.find('/18')]
tomorrow = f"{d[0:d.find('/')]}/{int(day_value)+1}{d[d.find('/18'):len(d)]}".format()
print(tomorrow)
# 8/17/18

Asegúrate de que la " cadena d " esté en forma de %m/%d/%Yforma que no tengas problemas para pasar de un mes al siguiente.

As Pash
fuente
2
si lo configura da 8/31/18continuación, esto vuelve 8/32/18. Si cambia el año 18, simplemente se rompe.
andrewsi