Bagaimana cara menambah datetime satu hari?

152

Bagaimana cara meningkatkan hari datetime?

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

Tetapi saya perlu melewati bulan dan tahun dengan benar? Ada ide?

Pol
sumber

Jawaban:

60

Tanggal yang bertambah dapat dicapai menggunakan objek timedelta:

import datetime

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

Mencari objek timedelta di dokumen Python: http://docs.python.org/library/datetime.html

Piotr Duda
sumber
12

Berikut adalah metode lain untuk menambahkan hari pada tanggal menggunakan relativedelta 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')

Keluaran:

Hari ini: 25/06/2015 20:41:44

After a Days: 01/06/2015 20:41:44

Atul Arvind
sumber
1
mengapa Anda menggunakannya bukan timedelta()dari stdlib?
jfs
2
@ JFSebastian Hanya untuk membagikan kemungkinan cara lain untuk menambah hari.
Atul Arvind
1
Jika tidak ada keuntungan, saya tidak berpikir itu menambah nilai.
Tejas Manohar
10

Semua jawaban saat ini salah dalam beberapa kasus karena mereka tidak menganggap bahwa zona waktu mengubah offsetnya relatif terhadap UTC. Jadi, dalam beberapa kasus, menambah 24 jam berbeda dengan menambahkan hari kalender.

Solusi yang diajukan

Solusi berikut berfungsi untuk Samoa dan menjaga waktu lokal tetap konstan.

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

Kode yang Diuji

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

Hasil tes

Method                   : Samoa   DST
relativedelta            :     0     0
timedelta                :     0     0
timedelta+conversion     :     1     0
timedelta+conversion+dst :     1     1
Martin Thoma
sumber
Jawaban yang lain tidak sepenuhnya salah, mereka baik-baik saja saat bekerja dengan UTC atau data naif ( tzinfo == None).
Delgan
3

Ini solusi mudah bagi saya:

from datetime import timedelta, datetime

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

Anda juga dapat mengimpor timedelta sehingga kodenya lebih bersih.

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

Kemudian konversikan ke tanggal menjadi string

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

Python one liner adalah

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

Solusi singkat tanpa perpustakaan sama sekali. :)

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

Pastikan " string d " benar-benar dalam bentuk %m/%d/%Ysehingga Anda tidak akan mengalami masalah transisi dari satu bulan ke bulan berikutnya.

Ace Pash
sumber
2
jika Anda mengatur duntuk 8/31/18kemudian kembali ini 8/32/18. Jika Anda mengubah tahun dari 18, itu hanya rusak.
andrewsi