Monate einer Woche ermitteln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Hallo,

ich hab jetzt schon eine Weile gesucht und jede Menge Möglichkeiten gefunden, aus einem Datum die Kalenderwoche zu ermitteln.

Ich brauche es allerdings genau andersrum: ich hab die Kalenderwoche und das Jahr gegeben und möchte den zugehörigen Monat ermitteln. Dazu habe ich allerdings nichts gefunden.

Gibt es da eine schnelle und einfach Möglichkeit?

Vielen Dank.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Du könntest es berechnen: Eine Woche hat 7 Tage. Bestimme den ersten und letzten Tag der Woche als Offset vom 1. Januar und bestimme dann deren Monat. Dieses Problem sehe ich als gelöst an. Zuvor muss man berücksichtigen, dass die erste Kalenderwoche die ist, in der mindestens 4 Tage liegen. Somit kann das Ergebnis für KW1 der Dezember des letzten Jahres sein. Gleiches gilt natürlich für die letzte Kalenderwoche, deren Ende im nächsten Jahr liegt.

Der brute-force-Ansatz ist aber vielleicht die einfachste Lösung:

Code: Alles auswählen

def year_and_month(year, kw):
  for d in range(366):
    dt = datetime.datetime(year, 1, 1) + datetime.timedelta(d)
    c = dt.isocalendar()
    if c[1] == kw:
      return c[0], dt.month # TODO mach's für den letzten Tag
  assert False
Stefan
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Anderer Ansatz -- aber auch mit probieren:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import time
import datetime


def months_of_the_week(year, week):
    week = int(week) - 1
    found_months = set()
    begin = datetime.date(year, 1, 1)
    for i in range(366):
        day = begin + datetime.timedelta(days = i)
        current_week = int(time.strftime("%W", day.timetuple()))
        if week == current_week:
            found_months.add(day.month)
        elif current_week > week:
            break
    return found_months


def main():
    print months_of_the_week(2008, 5)
    # Die Frage ist nur, was ist die erste Woche?
    # Es zählt der Montag als Wochenbeginn
    # -> set([1, 2]) Das bedeutet, dass die fünfte Woche auf den ersten und den
    # zweiten Monat fällt.


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Danke euch.

Ich hatte gehofft, dass es eine ganz einfach Funktion in einem der Timemodule gibt, die ich igendwie übersehen habe. Hatte befürchtet, dass es die nicht gibt, und ich dann quasi selber ausrechnen muss, aber wie ich sehe, ist das wohl doch die einzige MÖglichkeit.

Dann guck ich mir mal Eure Möglichkeiten an.

Danke sehr.

Hatte es sogar schon mit ner Dummy SQL-Abfrage probiert, aber auch das ging nicht:

'Select to_char(sysdate,'mm')
from dual
where to_char(sysdate,'iw') = '29''

(als Beispiel)

Dann wohl doch ausführlich.
lunar

Mit Berechnung (aus dem C#-Codebook geklaut):

Code: Alles auswählen

from datetime import date, timedelta

def isoweek_start_date(year, week):
    """Calculates the start date of the iso ``week`` in ``year``."""
    first_day_of_year = datetime(year, 1, 1)
    isoyear, isoweek, isoday = first_day_of_year.isocalendar()
    if isoweek != 1:
        # first day of year is in not the first week, but in the last week
        # of the last year
        first_day_of_year = first_day_of_year + timedelta(7)
    weekday = first_day_of_year.weekday()
    first_day_of_first_week = first_day_of_year - timedelta(weekday)
    return (first_day_of_first_week + timedelta((week-1) * 7)).date()

def isoweek_range(year, week):
    """Returns start and end date of the iso ``week`` in ``year``."""
    start = iso_week_start_date(week, year)
    return start, start+timedelta(6)
Btw, "range()" ohne Liste macht man besser mit "xrange()" ;)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

lunar hat geschrieben:Btw, "range()" ohne Liste macht man besser mit "xrange()" ;)
Hallo lunar!

``range()`` soll bei kleinen Zahlenreihen schneller als ``xrange()`` sein. Deshalb entscheide ich beim Programmieren nach Gefühl, ob es schon Zeit für ``xrange()`` ist oder ob ich doch noch ``range()`` verwende.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
lunar

gerold hat geschrieben:
lunar hat geschrieben:Btw, "range()" ohne Liste macht man besser mit "xrange()" ;)
Hallo lunar!

``range()`` soll bei kleinen Zahlenreihen schneller als ``xrange()`` sein. Deshalb entscheide ich beim Programmieren nach Gefühl, ob es schon Zeit für ``xrange()`` ist oder ob ich doch noch ``range()`` verwende.
Darf man fragen, woher du das hast? Ich kann mir das nämlich nicht vorstellen. Zwar sind beide Funktionen in C implementiert, aber trotzdem muss "range" ja noch eine Liste bauen.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

lunar hat geschrieben:Darf man fragen, woher du das hast?
Hallo lunar!

Das weiß ich leider nicht mehr. Aber eigentlich ist es mir immer logisch erschienen. Wenn ich eine Liste erstelle, dann kann ich das in einem Rutsch machen. Speicher reservieren und sofort mit Zahlen befüllen. Keine Tests zwischendrinnen. Keine Sprünge in andere Funktionen.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
lunar

gerold hat geschrieben:
lunar hat geschrieben:Darf man fragen, woher du das hast?
Hallo lunar!
Das weiß ich leider nicht mehr. Aber eigentlich ist es mir immer logisch erschienen. Wenn ich eine Liste erstelle, dann kann ich das in einem Rutsch machen. Speicher reservieren und sofort mit Zahlen befüllen. Keine Tests zwischendrinnen. Keine Sprünge in andere Funktionen.
Sprünge in Funktionen hat man in Python so oder so, "range()" führt ja auch nicht zur (effizienten) Iteration über ein C-Array, sondern zu einer Iteration über ein "list"-Objekt. Der Vergleich mit der oberen Grenze dürfte bei "xrange()" dagegen sehr effektiv sein, da die Doku nahelegt, dass er direkt auf C "long"s stattfindet, also ohne den "Umweg" über Pythonobjekte.

Diese Auffassung scheint zumindest mein "timeit" zu bestätigen:
Bild
"xrange()" ist ~0.3 Sekunden schneller.

Das verwendete Testskript: http://paste.pocoo.org/show/80325/
Und die Rohdaten: http://paste.pocoo.org/show/80326/
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Nur interessehalber: Was hast du zum Plotten verwendet?
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

lunar hat geschrieben:Bild
"xrange()" ist ~0.3 Sekunden schneller.
Hallo lunar!

Danke für's Testen. Dann ist 366 also schon zu viel für die normale Liste. Könntest du vielleicht noch ein paar kleine Werte austesten, damit man weiß, ab wann ``xrange()`` schneller ist?

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
lunar

Mit 5, 10, 20, 50, 70, 100, 150 und 200 Iterationen ergibt sich das gleiche Bild, "xrange()" ist durchweg schneller:
Bild

Messkript: http://paste.pocoo.org/show/80372/
Rohdaten: http://paste.pocoo.org/show/80373/
Plotskript: http://paste.pocoo.org/show/80374/
Zuletzt geändert von lunar am Samstag 26. Juli 2008, 13:29, insgesamt 1-mal geändert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

lunar hat geschrieben:Mit 5, 10, 20, 50, 70, 100, 150 und 200 Iterationen ergibt sich das gleiche Bild, "xrange()" ist durchweg schneller
Danke dir, Lunar!

Somit ist ``range()`` für so etwas "Geschichte". Schade ist nur, dass ich nicht mehr weiß wo das zu lesen war.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich finde ja: xrange() sieht einfach häßlich aus. Es erinnert nur daran, dass range() keine so gute Idee war, man dies aber nicht ändern wollte (xreadline ist noch so ein Kandidat) und schreit jedes Mal heraus, dass Python Designfehler mit sich herumschleppt. Daher benutze ich wenn es nicht wirklich zeitkritisch ist lieber range(). xrange() sollte sich ja auch Ende des Jahres mit Python 3.0 erledigt haben... ich hoffe jedenfalls auf einen schnellen Wechsel zu Python 3 und nicht so ein Krampf wie bei Java, wo auch noch Jahre nach dem Erscheinen von Java 5 immer noch generische Typen die Ausnahme bilden.

Stefan
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Ein ``range = xrange`` am Anfang des Moduls ist ja auch nicht ausgeschlossen...
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
lunar

sma hat geschrieben:Es erinnert nur daran, dass range() keine so gute Idee war, man dies aber nicht ändern wollte (xreadline ist noch so ein Kandidat) und schreit jedes Mal heraus, dass Python Designfehler mit sich herumschleppt.
Welche Sprache tut das nicht ...
Daher benutze ich wenn es nicht wirklich zeitkritisch ist lieber range().
Naja, es muss schon sehr "zeitkritisch" sein, bevor sich die Performance bei so kleinen Werten auswirkt ;) Ich habe ja auch nur gemessen, weil ich wissen wollte, ob "range" tatsächlich wider meine Erwartung schneller ist als xrange, weil ich mir das nicht vorstellen konnte. Würde ich auf reine Laufzeit wert legen, wäre ich nicht Python-Programmierer ;)

Code muss gut und elegant aussehen, schön zu lesen und leicht verständlich sein. Zu Gunsten dieses ehren Ziels opfere ich gerne die eine oder andere Millisekunde ;) Obwohl ich jetzt "xrange()" auch nicht so hässlich finde ...
xrange() sollte sich ja auch Ende des Jahres mit Python 3.0 erledigt haben... ich hoffe jedenfalls auf einen schnellen Wechsel zu Python 3
Ich halte es für ziemlich unwahrscheinlich, dass sich Python 3.0 so schnell durchsetzen wird. Ich glaube, du wirst auch nächstes Jahr noch mit "xrange" leben müssen ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

sma hat geschrieben:Ich finde ja: xrange() sieht einfach häßlich aus. Es erinnert nur daran, dass range() keine so gute Idee war, man dies aber nicht ändern wollte (xreadline ist noch so ein Kandidat) und schreit jedes Mal heraus, dass Python Designfehler mit sich herumschleppt.
Naja, range() war für die Zeit in der es eingeführt wurde durchaus eine gute Idee, nur Python hat sich weiterentwickelt und range() blieb stehen.
sma hat geschrieben:ich hoffe jedenfalls auf einen schnellen Wechsel zu Python 3 und nicht so ein Krampf wie bei Java, wo auch noch Jahre nach dem Erscheinen von Java 5 immer noch generische Typen die Ausnahme bilden.
Naja, Java 5 blieb ja abwärtskompatibel und generische Typen haben einfach wenig Programmierer-Zulauf, Python 3 ist das nicht und wenn wir bis 2010 eine breite Adaptationsrate sehen werden, würde ich das schon als gute Geschwindigkeit ansehen. Wenn ich mal gucke, wie lange es gedauert hat, bis Python 2.5 in die wichtigsten Distributionen gebraucht hat um Jahre nach dem Release mal die Standard-Python-Version zu werden. Die Python-Entwickler schließen ja ein Python 2.7 soweit ich noch aktuell bin, gar nicht aus. Ich für meinen Teil hoffe darauf, dass es nicht soweit kommen wird, aber man wird ja sehen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

wieso sieht xrange scheiße aus?

Ich finde es sehr schick.

Die plots gefallen mir btw. auch sehr gut :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

meneliel hat geschrieben:wieso sieht xrange scheiße aus?
Wegen dem ``x`` am Anfang, was ja nichts zur Bedeutung der Funktion beiträgt.

Auf die gleiche Weise wie ``zdir()``, ``tzip()`` ``gprint()`` etc hässlich wären wenn es sie gäbe. ``izip()`` und die restlichen Itertools sind da eine Ausnahme, da das ``i`` tatsächlich auch für etwas steht.

Edit: Typos.
Zuletzt geändert von Leonidas am Mittwoch 30. Juli 2008, 09:39, insgesamt 1-mal geändert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten