Jak obliczyć datę sześć miesięcy od bieżącej daty za pomocą modułu Python datetime?

391

Korzystam z modułu Python z datetime. Chcę obliczyć datę 6 miesięcy od bieżącej daty. Czy ktoś mógłby mi w tym pomóc?

Powodem, dla którego chcę wygenerować datę 6 miesięcy od bieżącej daty, jest wygenerowanie daty przeglądu . Jeśli użytkownik wprowadzi dane do systemu, data przeglądu będzie wynosić 6 miesięcy od daty ich wprowadzenia.

RailsSon
źródło
2
Będziesz musiał sprecyzować: kiedy jest sześć miesięcy od 31 marca? A od 30 sierpnia?
kmkaplan
3
Tak, edycja pomaga: oznacza to, że możesz w przybliżeniu od 6 miesięcy do 183 dni bez negatywnego wpływu. Dodanie 183 dni do dzisiaj wystarczy.
kmkaplan
15
Powyższe komentarze wydają mi się głupie. Koncepcja „dodania sześciu miesięcy” jest dość jasna - weź składnik miesiąca i dodaj 6go, ze wsparciem dla przechodzenia w ciągu roku (i cofania miesiąca do 1), jeśli przejdziemy do grudnia. Zdarza się to dokładnie tak, jak relativedeltarobi to i co robi każdy język programowania z obsługą tego rodzaju koncepcji.
Kirk Woll
5
@KirkWoll: Jestem pewien, że to całkiem jasne. Ale wciąż inny dla każdego, kto mówi. Python: date(2015, 3, 31) + relativedelta(months = 6)daje datetime.date(2015, 9, 30). Perl: DateTime->new(year=>2000, month=>3, day=>31)->add(months=>6)daje 2000-10-01T00:00:00. Php: date_create('2000-03-31', new DateTimeZone('UTC'))->add(new DateInterval('P6M'))daje 2000-10-01. Wybierz swoją truciznę.
kmkaplan
2
... dodanie 182 wydaje się bardziej pragmatyczne dla wygenerowania daty przeglądu : nie zmienia dnia tygodnia.
Wolf

Odpowiedzi:

1047

Uważam, że to rozwiązanie jest dobre. (Używa rozszerzenia Python-dateutil )

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

Zaletą tego podejścia jest to, że rozwiązuje problemy z 28, 30, 31 dniami itp. Staje się to bardzo przydatne w obsłudze reguł biznesowych i scenariuszy (np. Generowanie faktur itp.)

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)
Mahendra
źródło
2
+6 oznacza, że ​​może to być -6, to samo dotyczy również dni i lat :)
securecurve
5
@sliders_alpha Musisz zainstalować pakiet python-dateutil (instalacja pip python-dateutil)
poiuytrez
18
To jest właściwe rozwiązanie. Gdyby PO poprosiłby o 6 lat zamiast 6 miesięcy, wówczas zatwierdzona odpowiedź poniósłaby klęskę. Należy więc pamiętać, że odpowiedzi są tym cenniejsze, im bardziej są uogólnione.
Daniel F
3
Należy pamiętać, że relativedeltafunkcja przyjmuje również monthjako argument, który w zasadzie zastępuje / ustawia / naprawia miesiąc w podanym terminie, co jest zupełnie inne niż dodawanie kolejnych miesięcy. Tylko ostrzeżenie dla ludzi zastanawiających się, czy funkcja jest zepsuta, ponieważ zapomnieli o dodatkowej liczbie za kilka miesięcy .
shad0w_wa1k3r
1
Jestem ciekawy: czy ktoś wie, dlaczego nie jest to domyślnie uwzględnione? Timedelta datetimejest domyślnie zapakowana . Właściwie założyłem, że mogę przekazać „miesiące” na timedelta.
dTanMan,
51

To zależy od tego, co masz na myśli przez 6 miesięcy od bieżącej daty.

  1. Używając naturalnych miesięcy:

    (day, month, year) = (day, (month + 5) % 12 + 1, year + (month + 5)/12)
  2. Stosując definicję bankiera, 6 * 30:

    date += datetime.timedelta(6 * 30)
vartec
źródło
3
Czy możesz podać definicję półroczną (183 dni) plus definicję 26 tygodni? Pomaga mieć je wszystkie w jednym miejscu.
S.Lott,
11
tylko krótka uwaga: myślę, że dla miesiąca formuła będzie w zamian (miesiąc + 5)% 12 + 1 b / c dla czerwca, twoja formuła daje 0, podczas gdy oczekiwany wynik to 12 ... pomimo tego małego błędu, aby myślę, że twoja odpowiedź najlepiej odpowiada na pytanie
PierrOz
3
i to samo dla roku: powinien to być rok + (miesiąc + 5) / 12
PierrOz
7
Co jeśli data to 31, a miesiąc sześć miesięcy później nie może mieć 31 dni (tak jest w przypadku większości miesięcy z 31 dniami)?
akv
4
Oddaj głos, ponieważ pierwsze rozwiązanie (day, month, year) = (day, (month+6)%12, year+(month+6)/12)może się nie udać, ponieważ generuje niepoprawne daty, takie jak (31, 8, 2015)->(31, 2, 2016)
oh
37

W Pythonie 3.x możesz to zrobić w następujący sposób:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

ale musisz zainstalować moduł python-dateutil :

pip install python-dateutil
Luka Lopusina
źródło
Upvoted dlapip install ...
Nathan
Polecam from dateutil.relativedelta import relativedelta. Używanie import *nie jest jednoznaczne.
Sam Morgan
19

Na początku obliczeń z miesiąca na miesiąc:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
breddi
źródło
18
To nie jest rozwiązanie relativedelta wspomniane powyżej w komentarzach. Przewijaj rozwiązanie w poszukiwaniu ponad 600 głosów pozytywnych.
Nostalg.io
15

Co rozumiesz przez „6 miesięcy”?

Czy 2009-02-13 + 6 miesięcy == 2009-08-13? A może 2009-02-13 + 6 * 30 dni?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

Więcej informacji o mx.DateTime

Johannes Weiss
źródło
14

Oto przykład, dateutil.relativedeltaktóry uznałem za przydatny w iteracji przez ostatni rok, pomijając za każdym razem miesiąc do obecnej daty:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

Podobnie jak w przypadku innych odpowiedzi, musisz dowiedzieć się, co tak naprawdę rozumiesz przez „za 6 miesięcy”. Jeśli masz na myśli „dzisiejszy dzień miesiąca w miesiącu, który ma być sześć lat w przyszłości”, wówczas:

datetime.datetime.now() + relativedelta(months=6)
Dannyman
źródło
14

To rozwiązanie działa poprawnie w grudniu, czego większość odpowiedzi na tej stronie nie. Najpierw musisz przesunąć miesiące z podstawy 1 (tj. Jan = 1) na podstawę 0 (tj. Jan = 0) przed użyciem modułu (%) lub podziału na liczby całkowite (//), w przeciwnym razie listopad (11) plus 1 miesiąc daje 12 , co przy znalezieniu reszty (12% 12) daje 0.

(I nie sugeruj „(miesiąc% 12) + 1” lub październik + 1 = grudzień!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

Jednak ... To nie wyjaśnia problemu takiego jak 31 stycznia + jeden miesiąc. Wracamy więc do PO - co masz na myśli przez dodanie miesiąca? Jednym z rozwiązań jest wycofanie się, aż dojdziesz do ważnego dnia, biorąc pod uwagę, że większość ludzi przypuszcza, że ​​ostatni dzień stycznia, plus jeden miesiąc, równa się ostatniemu lutowi. To też zadziała w przypadku ujemnych liczb miesięcy. Dowód:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 
użytkownik417751
źródło
3
Naprawiono problem „31 stycznia + jeden miesiąc”: days_in_month = calendar.monthrange (newyear, newmonth) [1]; newday = min (d.day, days_in_month); (spowalnia dzień, jeśli jest zbyt duży, np. od 31 lutego do 28/29 lutego)
Curtis Yallop
Działa to tylko dla mnie poprzez konwersję newyear na typ danych całkowitych def AddMonths (d, x): newmonth = (((d.month - 1) + x)% 12) + 1 newyear = d.rok + int (( (d.miesiąc - 1) + x) / 12) return datetime.date (newyear, newmonth, d.day)
Manmeet Singh
12

Wiem, że trwało to 6 miesięcy, jednak odpowiedź wyświetla się w Google dla „dodawania miesięcy w pythonie”, jeśli dodajesz jeden miesiąc:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

to policzy dni w bieżącym miesiącu i doda je do bieżącej daty, użycie 365/12 spowoduje, że reklama 1/12 roku może powodować problemy z krótkimi / długimi miesiącami, jeśli iteracja w ciągu tej daty.

Mike Davies
źródło
11

Nie ma bezpośredniego sposobu na zrobienie tego z datetime Pythona.

Sprawdź typ relativedelta na python-dateutil . Pozwala określić deltę czasu w miesiącach.

Akbar ibrahim
źródło
10

Wystarczy użyć metody harmonogramu , aby wyodrębnić miesiące, dodać miesiące i zbudować nowy obiekt daty. Jeśli istnieje już taka metoda, nie wiem.

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

Interfejs API jest nieco niezdarny, ale działa jako przykład. Oczywiście nie zadziała również w przypadku takich przypadków, jak 31.01.2008 + 1 miesiąc. :)

Liczba Pi.
źródło
3
Błąd w kodzie: new_month % 12powinien być (new_month % 12) or 12. W przeciwnym razie, jeśli spróbujesz tego w listopadzie, pojawi się błąd. :)
Jordan Reiter
Jest to w rzeczywistości znacznie czystsze niż przyjęte rozwiązanie. Nie wymaga to żadnego nowego importu, tylko podstawowe matematyki
Simon PA
zwróć datetime.date (rok + (nowy_miesiąc / / 12), (nowy_miesiąc% 12) lub 12, dzień)
paytam
9

Pakiet Dateutil ma implementację takiej funkcjonalności. Pamiętaj jednak, że będzie to naiwne , jak już zauważyli inni.

zgoda
źródło
dateutil jest niesamowity. Można go również zainstalować za pomocą easy_install.
Soviut
Świetny. Dzięki za sugestię. To wydaje się być zesłane przez Boga.
ayaz
9

Używanie standardowych bibliotek Python, tj. Bez dateutillub innych, i rozwiązywanie problemu „31 lutego”:

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

Testowanie:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))
David Ragazzi
źródło
Ma to błąd: jeśli docelowym miesiącem jest grudzień, zwróci datę o rok później niż to konieczne. Przykład: add_months(datetime.date(2018, 11, 30), 1)zwroty datetime.date(2019, 12, 30)(rok powinien być 2018, a nie 2019). Lepiej więc użyj do tego dedykowanej, dobrze przetestowanej biblioteki! Jeśli naprawdę potrzebujesz tylko standardowych modułów bibliotecznych, zobacz moją odpowiedź na podobne pytanie .
taleinat
5

Mam lepszy sposób na rozwiązanie problemu „31 lutego”:

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

Myślę, że działa również z liczbami ujemnymi (aby odjąć miesiące), ale nie testowałem tego zbyt wiele.

amoyafoss
źródło
1
Ta odpowiedź ma tę zaletę, że poprawnie rozwiązuje problem przy użyciu tylko wbudowanych bibliotek Pythona. Sprawdź stackoverflow.com/a/4131114/302264, aby uzyskać równoważną, ale nieco bardziej zwięzłą odpowiedź.
Eduardo Dobay,
3

Klasa QDate PyQt4 ma funkcję addmonths.

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)
użytkownik213043
źródło
3

Co powiesz na to? Nie używasz innej biblioteki ( dateutil) lub timedelta? Opierając się na odpowiedzi firmy Vartec , zrobiłem to i uważam, że to działa:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

Próbowałem używać timedelta, ale ponieważ liczy dni, 365/2lub 6*356/12nie zawsze przekłada się na 6 miesięcy, ale raczej 182 dni. na przykład

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

Uważam, że zwykle zakładamy, że 6 miesięcy od pewnego dnia wyląduje tego samego dnia miesiąca, ale 6 miesięcy później (tj. 2015-03-10-> 2015-09-10, Nie 2015-09-08)

Mam nadzieję, że uznasz to za pomocne.

Babak K.
źródło
1
day + datetime.timedelta(6*365/12)nie zawsze będzie działać, ponieważ niektóre lata mają 365 dni, a inne 366 dni.
3kstc
3

To nie odpowiada na konkretne pytanie ( datetimetylko przy użyciu ), ale biorąc pod uwagę, że inni sugerowali użycie różnych modułów, tutaj jest rozwiązanie wykorzystujące pandas.

import datetime as dt
import pandas as pd

date = dt.date.today() - \
       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

Który działa zgodnie z oczekiwaniami w latach przestępnych

date = dt.datetime(2019,8,29) - \
       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00
rpanai
źródło
2

Zmodyfikowano AddMonths () do użytku w Zope i obsługi niepoprawnych numerów dni:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)
Jost
źródło
Wydaje się, że nie uwzględnia to lat przestępnych (29 dni w lutym).
uchwyt
2
import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))
Ares
źródło
1
import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))
Tony Diep
źródło
1

Zmodyfikowano odpowiedź Johannesa Wei w przypadku 1new_month = 121. To działa idealnie dla mnie. Miesiące mogą być dodatnie lub ujemne.

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)
Xinhui Tang
źródło
2
NIE „działa idealnie”, gdy dzień w dacie początkowej jest większy niż liczba dni w miesiącu docelowym. Przykład: 2001-01-31 plus jeden miesiąc próbuje utworzyć datę 2001-02-31.
John Machin
1

Jeszcze inne rozwiązanie - mam nadzieję, że komuś się spodoba:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

To rozwiązanie nie działa przez 29, 30, 31 dni we wszystkich przypadkach, dlatego potrzebne jest bardziej niezawodne rozwiązanie (które nie jest już tak miłe :)):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")
Robert Lujo
źródło
1

Z tej odpowiedzi zobacz parsedatetime . Poniższy przykład kodu. Więcej informacji: test jednostkowy z wieloma przykładami konwersji w języku naturalnym -> RRRR-MM-DD i pozorne wyzwania / błędy konwersji w czasie parsowanym .

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

Powyższy kod generuje następujące dane z komputera MacOSX:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 
Johnny Utahh
źródło
1

Oto przykład, który pozwala użytkownikowi zdecydować, jak zwrócić datę, w której dzień jest większy niż liczba dni w miesiącu.

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)
Bruce Jakeway
źródło
1

biorąc pod uwagę, że zmienna data-godzina nazywa się data:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)
blacknight12321
źródło
1

Ogólna funkcja, aby uzyskać następną datę po / przed x miesiącami.

od daty importu daty / godziny

def after_month (podana data, miesiąc):
    rrrr = int (((podano_datę.rok * 12 + podano_datę.miesiąc) + miesiąc) / 12)
    mm = int (((podana_data.rok * 12 + podana_data.miesiąc) + miesiąc)% 12)

    jeśli mm == 0:
        rrrr - = 1
        mm = 12
    zwróć dane_data.replace (rok = rrrr, miesiąc = mm)


jeśli __name__ == "__main__":
    Today = date.today ()
    drukuj (dzisiaj)

    dla mm w [-12, -1, 0, 1, 2, 12, 20]:
        next_date = after_month (dzisiaj, mm)
        drukuj (data_dalej)
Nandlal Yadav
źródło
To jest zdecydowanie najlepsza odpowiedź. Prosty i skuteczny, bez problemów z zaokrąglaniem.
jprobichaud
1

Szybką sugestią jest Arrow

strzałka instalacji pip

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)
Diego Magalhães
źródło
0

Użyj modułu datetime w Pythonie, aby dodać sześciomiesięczną timedelta do datetime.today ().

http://docs.python.org/library/datetime.html

Będziesz oczywiście musiał rozwiązać kwestię podniesioną przez Johannesa Weiß-- co ma na myśli przez 6 miesięcy?

Devin Jeanpierre
źródło
1
timedelta nie obsługuje miesięcy, dlatego omija możliwe odpowiedzi na pytanie „ile dni w ciągu 6 miesięcy?” Kod Eefa ustawi datę przeglądu, więc sugerowałbym, aby rozważyć ustawienie timedelty za pomocą dni (6 * 30). Jeśli okres reprezentuje dostęp klientów do produktu / usługi, może być wymagana / preferowana definicja biznesowa.
Carl
0

Właśnie to wymyśliłem. Przenosi prawidłową liczbę miesięcy i lat, ale ignoruje dni (to było to, czego potrzebowałem w mojej sytuacji).

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)
Marshallpenguin
źródło
0

Używam tej funkcji do zmiany roku i miesiąca, ale zachowuję dzień:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

Powinieneś napisać:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)
gt_rocker
źródło
0

Myślę, że bezpieczniej byłoby zrobić coś takiego zamiast ręcznie dodawać dni:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)
DataGreed
źródło