2008-09-30 8 views

Odpowiedz

75

Zastosowanie dateutil a jego realizacja rrule, tak:

from dateutil import rrule 
from datetime import datetime, timedelta 

now = datetime.now() 
hundredDaysLater = now + timedelta(days=100) 

for dt in rrule.rrule(rrule.MONTHLY, dtstart=now, until=hundredDaysLater): 
    print dt 

Wyjście jest

2008-09-30 23:29:54 
2008-10-30 23:29:54 
2008-11-30 23:29:54 
2008-12-30 23:29:54 

Wymień MIESIĘCZNIE na LICZBA, MIESIĘCZNIE, COTYGODNIE, CODZIENNIE, GODZINA, MINUTNIE LUB DRUGI. Zamień dtstart i aż do dowolnego obiektu datetime, który chcesz.

Ten przepis ma tę zaletę, że działa we wszystkich przypadkach, w tym MIESIĘCZNIE. Jedyne zastrzeżenie, jakie mogłem znaleźć, to to, że jeśli przekażesz numer dnia, który nie istnieje przez wszystkie miesiące, pomija te miesiące.

+1

http://niemeyer.net/python-dateutil wyjaśnia, jak użyć go do pobrania "daty w określonym dniu miesiąca, chyba że jest poza nią koniec miesiąca, w którym to przypadku będzie to ostatni dzień miesiąca ". To naprawia jedno z wymienionych ostrzeżeń. Jako przykład: teraz = datetime (2010, 8, 31, 1, 1, 1); dla dt w rrule.rrule (rrule.MONTHLY, dtstart = teraz, bymonthday = (31, -1), count = 6): print dt – Smerity

38

Nie sądzę, istnieje metoda w biblioteki Pythona, ale łatwo można tworzyć samemu, używając modułu datetime:

from datetime import date, datetime, timedelta 

def datespan(startDate, endDate, delta=timedelta(days=1)): 
    currentDate = startDate 
    while currentDate < endDate: 
     yield currentDate 
     currentDate += delta 

Następnie można go używać tak:

>>> for day in datespan(date(2007, 3, 30), date(2007, 4, 3), 
>>>      delta=timedelta(days=1)): 
>>>  print day 
2007-03-30 
2007-03-31 
2007-04-01 
2007-04-02 

Albo, jeśli chcesz, aby Twój delta mniejszy:

>>> for timestamp in datespan(datetime(2007, 3, 30, 15, 30), 
>>>       datetime(2007, 3, 30, 18, 35), 
>>>       delta=timedelta(hours=1)): 
>>>  print timestamp 
2007-03-30 15:30:00 
2007-03-30 16:30:00 
2007-03-30 17:30:00 
2007-03-30 18:30:00 
+1

Nie można określić timedelta jednego miesiąca – dangonfast

6

Do iteracji przez miesiące potrzebny jest inny przepis, ponieważ timedeltas nie może wyrazić "jeden miesiąc".

from datetime import date 

def jump_by_month(start_date, end_date, month_step=1): 
    current_date = start_date 
    while current_date < end_date: 
     yield current_date 
     carry, new_month = divmod(current_date.month - 1 + month_step, 12) 
     new_month += 1 
     current_date = current_date.replace(year=current_date.year + carry, 
              month=new_month) 

(Uwaga: trzeba odjąć od 1 miesiąca do operacji moduł następnie dodać go do new_month, od miesięcy w datetime.date s rozpoczynają się od 1.)

+0

Dwie rzeczy: - ten kod podnosi "ValueError", jeśli ustawisz dzień_początku na liczbę, która nie istnieje w każdym miesiącu - prawdopodobnie, właśnie z tego powodu nie ma miesiąca -timedelta; Sugerowałbym użycie 'timedelta (days = 30)' dla dobrego przybliżenia. – DzinX

+0

Dobry połów. Czasami jednak przybliżenie nie jest wystarczająco dobre (moje przypomnienie "zapłać mi czynsz" * ma * być o 6:30 pierwszego dnia każdego miesiąca). Przepis można zmodyfikować - prawdopodobnie z dodatkowym stanem - aby zapewnić rozsądną funkcjonalność, cokolwiek to jest. – giltay

+0

Możesz również napotkać problemy powtarzające się rok po roku 29 lutego. – giltay

-2

Należy zmodyfikować ten wiersz do tej pracy poprawnie:

current_date = current_date.replace (rok = current_date.year + Torba, miesiąc = new_month, dzień = 1)

;)

0

Miesiąc podejście iteracja:

def months_between(date_start, date_end): 
    months = [] 

    # Make sure start_date is smaller than end_date 
    if date_start > date_end: 
     tmp = date_start 
     date_start = date_end 
     date_end = tmp 

    tmp_date = date_start 
    while tmp_date.month <= date_end.month or tmp_date.year < date_end.year: 
     months.append(tmp_date) # Here you could do for example: months.append(datetime.datetime.strftime(tmp_date, "%b '%y")) 

     if tmp_date.month == 12: # New year 
      tmp_date = datetime.date(tmp_date.year + 1, 1, 1) 
     else: 
      tmp_date = datetime.date(tmp_date.year, tmp_date.month + 1, 1) 
    return months 

więcej kodu, ale będzie to robić grzywny do czynienia z długich okresach czasu sprawdzając, czy podane daty są w porządku ...

Powiązane problemy