Seite 1 von 1

Liste der Wochen eines Jahres

Verfasst: Samstag 15. März 2008, 23:00
von blinky
Liebe Pythonisten,

nach einigem Herumgehacke mit Django habe ich mir zum Ziel gesetzt, Python langfristig ein bisschen besser zu lernen. Dazu möchte ich gerne einen Kalendar in Python erstellen. Ich würde gerne entweder Daten generieren, die später in InDesign importiert werden können, oder direkt eine PDF-Datei erstellen (pyCairo gefällt mir ganz gut).

Nun möchte ich gerne für jede Woche im Jahr eine Seite erzeugen. Dazu stelle ich mir eine Liste vor, die die Wochen des Jahres enthält, die wiederum (als Listen) die jeweiligen Tage als datetime.date-Objekte enthalten. Diese Liste würde ich dann durchiterieren, um den Kalender zu erzeugen.

Im Moment verwende ich den Output aus dem calendar-Modul(mit mäßigem Erfolg), frage mich aber, ob es nicht doch einen einfacheren und eleganteren Weg gibt, eine solche Liste zu erzeugen. Ich wäre Euch riesig dankbar, wenn ihr mir einen Tipp geben könntet oder einen Hinweis, in welchem Bereich ich suchen sollte.

Vielen Dank


Blinky

Verfasst: Sonntag 16. März 2008, 09:17
von Nikolas
Schau dir mal hier den dritten Post an.
http://www.daniweb.com/forums/post148294-3.html

Code: Alles auswählen

for month in range(1,12): # oder 13?
  for day in range(1,32):
      Datum erstellen
      prüfen, ob man nicht gerade den 31.2 oder so was erstellt hat
      prüfen, ob dayOfWeek==0 (Montag)
      -> du hast einen neuen Eintrag für deine Liste

Verfasst: Sonntag 16. März 2008, 11:25
von Trundle
Man könnte die `monthdatescalendar`-Methode eines `Calendar`-Objekts benutzen. Die liefert einem ja schon `datetime.date`-Objekte. Man müsste eben nur überprüfen, ob die Woche am Anfang eines Monats nicht die letzte Woche des vorherigen Monats ist (weil ja immer 7 Tage aufgefüllt werden).
Könnte vielleicht so aussehen:

Code: Alles auswählen

from calendar import Calendar

cal = Calendar()
weeks = list()
for month in xrange(1, 13):
    for week in cal.monthdatescalendar(2008, month):
        if not weeks or weeks[-1] != week:
            weeks.append(week)
# `weeks` ist nun eine Liste mit allen Wochen des Jahres 2008,
# die wiederum eine Liste mit 7 `datetime.date`-Objekten sind

Verfasst: Sonntag 16. März 2008, 11:48
von rayo
Hi

Ich würde das so lösen, reicht ja immer den Montag der Woche zu nehmen :)

Code: Alles auswählen

import datetime

def get_weeks(year):
    weeks = []
    
    # 1. Januar 
    first = datetime.date(year, 1, 1)
    
    # Montag in der 1. Woche
    current = first-datetime.timedelta(days=first.weekday())
    
    one_week = datetime.timedelta(days=7)
    
    # kalender jahr == gewuenschtes jahr
    while current.isocalendar()[0] == year:
        # Tuple aus Wochennummer, Startdatum (Montag)
        weeks.append((current.isocalendar()[1], current))
        
        # naechste Woche
        current += one_week
    
    return weeks
    
print get_weeks(2008)
Ausgabe:

Code: Alles auswählen

[(1, datetime.date(2007, 12, 31)),
 (2, datetime.date(2008, 1, 7)),
 (3, datetime.date(2008, 1, 14)),
 (4, datetime.date(2008, 1, 21)),
 (5, datetime.date(2008, 1, 28)),
 (6, datetime.date(2008, 2, 4)),
 (7, datetime.date(2008, 2, 11)),
 (8, datetime.date(2008, 2, 18)),
 (9, datetime.date(2008, 2, 25)),
 (10, datetime.date(2008, 3, 3)),
 (11, datetime.date(2008, 3, 10)),
 (12, datetime.date(2008, 3, 17)),
 (13, datetime.date(2008, 3, 24)),
 (14, datetime.date(2008, 3, 31)),
 (15, datetime.date(2008, 4, 7)),
 (16, datetime.date(2008, 4, 14)),
 (17, datetime.date(2008, 4, 21)),
 (18, datetime.date(2008, 4, 28)),
 (19, datetime.date(2008, 5, 5)),
 (20, datetime.date(2008, 5, 12)),
 (21, datetime.date(2008, 5, 19)),
 (22, datetime.date(2008, 5, 26)),
 (23, datetime.date(2008, 6, 2)),
 (24, datetime.date(2008, 6, 9)),
 (25, datetime.date(2008, 6, 16)),
 (26, datetime.date(2008, 6, 23)),
 (27, datetime.date(2008, 6, 30)),
 (28, datetime.date(2008, 7, 7)),
 (29, datetime.date(2008, 7, 14)),
 (30, datetime.date(2008, 7, 21)),
 (31, datetime.date(2008, 7, 28)),
 (32, datetime.date(2008, 8, 4)),
 (33, datetime.date(2008, 8, 11)),
 (34, datetime.date(2008, 8, 18)),
 (35, datetime.date(2008, 8, 25)),
 (36, datetime.date(2008, 9, 1)),
 (37, datetime.date(2008, 9, 8)),
 (38, datetime.date(2008, 9, 15)),
 (39, datetime.date(2008, 9, 22)),
 (40, datetime.date(2008, 9, 29)),
 (41, datetime.date(2008, 10, 6)),
 (42, datetime.date(2008, 10, 13)),
 (43, datetime.date(2008, 10, 20)),
 (44, datetime.date(2008, 10, 27)),
 (45, datetime.date(2008, 11, 3)),
 (46, datetime.date(2008, 11, 10)),
 (47, datetime.date(2008, 11, 17)),
 (48, datetime.date(2008, 11, 24)),
 (49, datetime.date(2008, 12, 1)),
 (50, datetime.date(2008, 12, 8)),
 (51, datetime.date(2008, 12, 15)),
 (52, datetime.date(2008, 12, 22))]
Gruss

Verfasst: Sonntag 16. März 2008, 12:57
von blinky
Hej,

wow, riesigen Dank für eure schnellen und hilfreichen Antworten! Die haben mir schon riesig weitergeholfen.

Vielen Dank erstmal an Nikolas - eine ähnliche Lösung habe ich gerade am laufen (hätte ich vielleicht auch posten können - sorry!). Sie erfasst mit calendar.monthrange() die Länge eines Monats und iteriert ihn dann durch.

Größen Dank auch an Trundle für die innovative Lösung - so hätte ich mir das vorgestellt, nur kam ich irgendwie nicht an die Calendar()-Klasse dran. Jetzt weiß ich, was ich bei meinen Versuchen falsch gemacht hatte: Ich hätte die Klasse explizit importieren (wie das auch im Code gemacht wurde) oder cal = calendar.Calendar() schreiben müssen.

Sehr gut gefällt mir auch die Lösung von Rayo, danke! Das datetime-Modul scheint ja ziemlich flexibel zu sein - das werde ich mir auf jeden fall mal anschauen.

Ok - Ich werde, denke ich, die ganzen Vorschläge ein bisschen kombinieren und mal sehen, was rauskommt. Nochmal vielen Dank!

Blinky

PS: Ich weiß nicht, wie es hier im Forum üblich ist: Sollte ich diesen Thread irgendwie als gelöst markieren?

Verfasst: Sonntag 16. März 2008, 13:42
von Leonidas
blinky hat geschrieben:PS: Ich weiß nicht, wie es hier im Forum üblich ist: Sollte ich diesen Thread irgendwie als gelöst markieren?
Nein, aus guten, schon öfter diskutierten Gründen solltest du den so lassen wie er ist. Wir finden, dass gelöst-Markierungen kontraproduktiv sind.

Verfasst: Sonntag 16. März 2008, 14:02
von HWK
Trundle hat geschrieben:Man könnte die `monthdatescalendar`-Methode eines `Calendar`-Objekts benutzen. Die liefert einem ja schon `datetime.date`-Objekte. Man müsste eben nur überprüfen, ob die Woche am Anfang eines Monats nicht die letzte Woche des vorherigen Monats ist (weil ja immer 7 Tage aufgefüllt werden).
Könnte vielleicht so aussehen:

Code: Alles auswählen

from calendar import Calendar

cal = Calendar()
weeks = list()
for month in xrange(1, 13):
    for week in cal.monthdatescalendar(2008, month):
        if not weeks or weeks[-1] != week:
            weeks.append(week)
# `weeks` ist nun eine Liste mit allen Wochen des Jahres 2008,
# die wiederum eine Liste mit 7 `datetime.date`-Objekten sind
Calendar.monthdatescalendar scheint es aber erst ab Python 2.5 zu geben.

Verfasst: Sonntag 16. März 2008, 14:37
von Trundle
HWK hat geschrieben:Calendar.monthdatescalendar scheint es aber erst ab Python 2.5 zu geben.
`calendar.Calendar` gibt es erst ab Python2.5.

Verfasst: Sonntag 16. März 2008, 15:07
von blinky
Leonidas hat geschrieben: [...] aus guten, schon öfter diskutierten Gründen solltest du den so lassen wie er ist. Wir finden, dass gelöst-Markierungen kontraproduktiv sind.
Danke für die Antwort von höchster Stelle - wird gemacht! :D

Vielleicht noch eine Frage: Wäre es zulässig, einfach "calendar.Calendar().monthdatescalendar(year, month)" zu schreiben, anstelle einen Kalender zu initialisieren? Hat das irgendwelche Nachteile (oder ist es stilistisch schlecht oder beides)?

Verfasst: Sonntag 16. März 2008, 17:23
von Leonidas
blinky hat geschrieben:Vielleicht noch eine Frage: Wäre es zulässig, einfach "calendar.Calendar().monthdatescalendar(year, month)" zu schreiben, anstelle einen Kalender zu initialisieren? Hat das irgendwelche Nachteile (oder ist es stilistisch schlecht oder beides)?
Nein, solange du die nicht brauchst macht das eigentlich keinen Unterschied. Es ist aber recht lang und somit könntest du über die 79-Zeichen Zeilenlänge kommen, was nicht so sonderlich gerne gesehen wird, wenn du die überschreitest.