Bir tarih saati nasıl bir gün artırılır?


161

Bir tarih saatinin gününü nasıl artırabilirim?

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

Ama ayları ve yılları doğru bir şekilde geçirmem gerekiyor? Herhangi bir fikir?

Yanıtlar:




13

İşte dateutil'in relativedelta'sını kullanarak tarihe gün eklemek için başka bir yöntem.

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

Çıktı:

Bugün: 25/06/2015 20:41:44

Bir Gün Sonra: 01/06/2015 20:41:44


1
neden timedelta()stdlib yerine kullanasınız?
jfs

2
@JFSebastian Gün eklemenin olası başka bir yolunu paylaşmak için.
Atul Arvind

1
Avantaj yoksa değer katacağını düşünmüyorum.
Tejas Manohar

11

Saat dilimlerinin UTC'ye göre farklarını değiştirdiğini düşünmedikleri için bazı durumlarda mevcut yanıtların tümü yanlıştır. Bu nedenle bazı durumlarda 24 saat eklemek, takvim günü eklemekten farklıdır.

Önerilen çözüm

Aşağıdaki çözüm Samoa için çalışıyor ve yerel saati sabit tutuyor.

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

Test Edilmiş Kod

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

Test sonuçları

Method                   : Samoa   DST
relativedelta            :     0     0
timedelta                :     0     0
timedelta+conversion     :     1     0
timedelta+conversion+dst :     1     1

1
Diğer cevaplar tamamen yanlış değil, UTC veya naif ( tzinfo == None) veri zamanlarıyla çalışırken mükemmel derecede iyi .
Delgan

4

Bu benim için basit bir çözümdü:

from datetime import timedelta, datetime

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


Bu, OP sorusuna doğrudan yanıt vermez, çünkü today()kabul edilen yanıtı varsayar ve bu kadar iyi değildir çünkü varsayılan artış biriminin olduğunu varsayar days.
MarkHu

@MarkHu Cevabımın kabul edilmesi gerektiğini tartışmıyorum. Ancak, varsayımın ne için olduğu today()ve neden kötü bir varsayım olduğunu açıklayabilir misiniz? Ayrıca soru günlerdir sormuyor mu? Kabul edilen cevabın daha genel bir ifade olduğu ifadesi mi?
Aus_10

1. OP bugün değil, rastgele bir tarihten sonraki ertesi günü nasıl bulacağını sordu. Örnek kodunuz todaybir dize olarak adlandırılan bir değişken atadı , sonra onu hiç kullanmadı. Daha iyi: date = datetime.today()2. Son satırınız kodlanmış today()ve ilk timedeltabağımsız değişkeni days(bu doğru olabilir, ama neden açıklık için adlandırmıyorsunuz?) Daha iyi: laterDate = date + timedelta(days=1)# IMHO :)
MarkHu

0

Ayrıca timedelta'yı içe aktararak kodun daha temiz olmasını sağlayabilirsiniz.

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

Sonra tarihe dizeye dönüştür

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

Python tek satırlık

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

-2

Hiç kitaplık içermeyen kısa bir çözüm. :)

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

Bir aydan diğerine geçişte sorun yaşamamanız için " string d " nin aslında şeklinde olduğundan emin olun %m/%d/%Y.


2
Eğer ayarlarsanız diçin 8/31/18o zaman bu döner 8/32/18. Yıldan itibaren değiştirirseniz, 18sadece kırılır.
andrewsi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.