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:

Monate einer Woche ermitteln

Beitragvon meneliel » Freitag 25. Juli 2008, 11:11

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

Beitragvon sma » Freitag 25. Juli 2008, 11:44

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: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Freitag 25. Juli 2008, 11:57

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:

Beitragvon meneliel » Freitag 25. Juli 2008, 12:32

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

Beitragvon lunar » Freitag 25. Juli 2008, 13:08

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: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Freitag 25. Juli 2008, 13:15

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

Beitragvon lunar » Freitag 25. Juli 2008, 13:30

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: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Freitag 25. Juli 2008, 13:56

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

Beitragvon lunar » Freitag 25. Juli 2008, 22:27

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

Beitragvon birkenfeld » Freitag 25. Juli 2008, 22:38

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

http://pythonic.pocoo.org/
lunar

Beitragvon lunar » Freitag 25. Juli 2008, 23:10

Gnuplot. FWIW, das Gnuplot Skript
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Samstag 26. Juli 2008, 10:23

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

Beitragvon lunar » Samstag 26. Juli 2008, 12:39

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: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Samstag 26. Juli 2008, 12:57

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

Beitragvon sma » Samstag 26. Juli 2008, 17:05

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

Wer ist online?

Mitglieder in diesem Forum: redone