Gegeben ein Datum, wie zu berechnen die Anzahl der Wochenenden oder Schecks ganz oder teilweise in diesem Bereich?

StackOverflow https://stackoverflow.com/questions/883615

  •  22-08-2019
  •  | 
  •  

Frage

Gegeben ein Datum, wie zu berechnen die Anzahl der Wochenenden oder Schecks ganz oder teilweise in diesem Bereich?

(Ein paar Definitionen wie gewünscht:nehmen Sie 'Wochenende' bedeutet Samstag und Sonntag.Der Datumsbereich ist inclusive, d.h.das Enddatum ist ein Teil der Reihe 'ganz oder teilweise' bedeutet, dass jeder Teil des Wochenendes fallen dem Datumsbereich bedeutet das ganze Wochenende gezählt wird.)

Zur Vereinfachung Stelle ich mir Sie eigentlich nur brauchen zu wissen, der Dauer und an welchem Tag der Woche der erste Tag ist...

Ich verdammt gut jetzt, es wird beinhalten zu tun integer-division durch 7 und eine gewisse Logik zu 1 hinzufügen, je nach dem Rest, aber ich kann nicht ganz herausfinden, was...

extra-Punkte für Antworten in Python ;-)

Bearbeiten

Hier ist mein endgültiger code.

Am Wochenende ist Freitag und Samstag (als wir zählen übernachtungen) und die Tage sind 0-indiziert, beginnend vom Montag.Ich verwendet onebyone-Algorithmus und Tom ' s code-layout.Vielen Dank Leute.

def calc_weekends(start_day, duration):
    days_until_weekend = [5, 4, 3, 2, 1, 1, 6]
    adjusted_duration = duration - days_until_weekend[start_day]
    if adjusted_duration < 0:
        weekends = 0
    else:
        weekends = (adjusted_duration/7)+1
    if start_day == 5 and duration % 7 == 0: #Saturday to Saturday is an exception
        weekends += 1
    return weekends

if __name__ == "__main__":
    days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    for start_day in range(0,7):
        for duration in range(1,16):
            print "%s to %s (%s days): %s weekends" % (days[start_day], days[(start_day+duration) % 7], duration, calc_weekends(start_day, duration))
        print
War es hilfreich?

Lösung

Der Allgemeine Ansatz für diese Art von Sache:

Für jeden Tag der Woche, um herauszufinden, wie viele Tage sind erforderlich, bevor ein Zeitraum ab diesem Tag "enthält ein Wochenende".Zum Beispiel, wenn "enthält ein Wochenende" bedeutet "enthält sowohl den Samstag und den Sonntag", dann haben wir die folgende Tabelle:

Sonntag:8 Montag:7 Dienstag:6 Mittwoch:5 Donnerstag:4 Freitag:3 Samstag:2

Für "teilweise oder vollständig", haben wir:

Sonntag:1 Montag:6 Dienstag:5 Mittwoch:4 Donnerstag:3 Freitag:2 Samstag:1

Offensichtlich ist dies nicht codiert werden müssen, wie Sie eine Tabelle, jetzt, dass es offensichtlich ist, wie es aussieht.

Dann, da die Tag-der-Woche der start der Periode, subtrahieren[*] den magischen Wert von der Länge des Zeitraums in Tagen (wahrscheinlich Anfang-Ende+1, beide fenceposts).Wenn das Ergebnis kleiner als 0 ist, enthält es 0 Wochenenden.Wenn es gleich oder größer als 0, so enthält es (mindestens) 1-Wochenende.

Dann müssen Sie sich mit den verbleibenden Tagen.Im ersten Fall ist dies einfach, ein extra Wochenende pro volle 7 Tage.Dies gilt auch im zweiten Fall für jeden Start-Tag außer Sonntag, die erfordert nur 6 Tage zu zählen anderen Wochenende.So in dem zweiten Fall für Perioden beginnend am Sonntag könnten Sie zählen 1-Wochenende am Anfang der Periode, dann subtrahieren Sie 1 von der Länge und der Neuberechnung vom Montag.

Mehr in der Regel, was dort geschieht, für "ganz oder teilweise" Wochenende ist, dass wir prüfen, ob wir starten in der Mitte durch das interessante bit ("weekend").Wenn dem so ist, können wir entweder:

  • 1) Zählen, eins, verschieben Sie die start-Datum für das Ende des interessanten wenig, und neu berechnen.
  • 2) Verschieben Sie den start-Datum zurück zu Beginn des interessanten wenig, und neu berechnen.

Im Falle der Wochenenden, es gibt nur einen Sonderfall, der beginnt in der Mitte, also (1) gut aussieht.Aber wenn Sie immer das Datum als Datum+Zeit in Sekunden, anstatt Tage, oder wenn Sie daran interessiert waren, in 5-Tage-Arbeitswochen eher als 2-Tages-Wochenende, dann (2) möglicherweise einfacher zu verstehen.

[*] Es sei denn, Sie sind mit nicht signierten Typen, natürlich.

Andere Tipps

Mein allgemeiner Ansatz für diese Art der Sache:don ' T start messing herum und versuchte, zu implementieren Ihre eigenen Datum Logik - es ist schwer, ie.Sie werden Schrauben Sie es bis zum Rand Fällen und schlecht Aussehen. Hinweis: wenn Sie mod 7 arithmetische überall in Ihrem Programm, oder sind die Behandlung von Daten als Ganzzahlen überall in Ihrem Programm: Sie scheitern.Wenn ich sah die "akzeptierte Lösung" irgendwo in (oder sogar in der Nähe) meine Codebasis, jemand würde von vorne beginnen müssen.Es Bettlern die Vorstellung, dass jeder, der sieht sich ein Programmierer würde Stimmen, dass die Antwort bis.

Verwenden Sie stattdessen die integrierte Datum - /Zeit-Logik, die kommt mit Python:

Zunächst erhalten Sie eine Liste aller von den Tagen, an denen Sie interessiert sind:

from datetime import date, timedelta    
FRI = 5; SAT = 6

# a couple of random test dates
now = date.today()
start_date = now - timedelta(57)
end_date = now - timedelta(13)
print start_date, '...', end_date    # debug

days = [date.fromordinal(d) for d in  
            range( start_date.toordinal(),
                   end_date.toordinal()+1 )]

Als Nächstes filtern, um nur die Tage, die Wochenenden sind.In Ihrem Fall sind Sie daran interessiert, Freitag und Samstag Nächte, die sind 5 und 6.(Beachten Sie, wie ich versuche nicht, Rollen Sie diesen Teil in der vorherigen Liste Verständnis, da, dass würde schwer sein, zu überprüfen, wie korrekt).

weekend_days = [d for d in days if d.weekday() in (FRI,SAT)]

for day in weekend_days:      # debug
    print day, day.weekday()  # debug

Schließlich möchten Sie herausfinden, wie viele Wochenenden sind in der Liste.Dies ist der schwierige Teil, aber es sind wirklich nur vier Fälle zu betrachten, eine für jedes Ende entweder Freitag oder Samstag.Konkrete Beispiele helfen, machen es klarer, und dies ist wirklich die Art von Sache, die Sie wollen, dokumentiert in Ihrem code:

num_weekends = len(weekend_days) // 2

# if we start on Friday and end on Saturday we're ok,
# otherwise add one weekend
#  
# F,S|F,S|F,S   ==3 and 3we, +0
# F,S|F,S|F     ==2 but 3we, +1
# S|F,S|F,S     ==2 but 3we, +1
# S|F,S|F       ==2 but 3we, +1

ends = (weekend_days[0].weekday(), weekend_days[-1].weekday())
if ends != (FRI, SAT):
    num_weekends += 1

print num_weekends    # your answer

Kürzer, klarer und leichter zu verstehen, bedeutet, dass Sie mehr Vertrauen in Ihren code und können mit interessanter Probleme.

Zählen ganze Wochenende, nur passen Sie die Zahl der Tage, so dass Sie beginnen an einem Montag, dann geteilt durch sieben.(Beachten Sie, dass, wenn das start-Tag ist ein Wochentag, hinzufügen von Tagen zu bewegen, um den vorherigen Montag, und wenn es auf ein Wochenende, subtrahieren Tage zu verschieben, um den nächsten Montag, da Sie schon verpasst an diesem Wochenende.)

days = {"Saturday":-2, "Sunday":-1, "Monday":0, "Tuesday":1, "Wednesday":2, "Thursday":3, "Friday":4}

def n_full_weekends(n_days, start_day):
    n_days += days[start_day]
    if n_days <= 0:
        n_weekends = 0
    else:
        n_weekends = n_days//7
    return n_weekends

if __name__ == "__main__":
    tests = [("Tuesday", 10, 1), ("Monday", 7, 1), ("Wednesday", 21, 3), ("Saturday", 1, 0), ("Friday", 1, 0),
    ("Friday", 3, 1), ("Wednesday", 3, 0), ("Sunday", 8, 1), ("Sunday", 21, 2)]
    for start_day, n_days, expected in tests:
        print start_day, n_days, expected, n_full_weekends(n_days, start_day)

Wenn Sie wissen wollen, teilweise an den Wochenenden (oder Wochen), schauen Sie sich nur den Bruchteil der division durch sieben.

Sie würde benötigen die externe Logik neben raw-math.Benötigen Sie eine Kalender-Bibliothek (oder wenn Sie haben eine anständige Menge an Zeit, es selbst implementieren), um zu definieren, was ein Wochenende, an welchem Tag der Woche Sie auf start, Ende, usw.

Werfen Sie einen Blick auf Python-Kalender-Klasse.

Ohne eine logische definition der Tage in Ihrem code, eine Reine mathematische Methoden scheitern an der Ecke Fall, wie ein Intervall von 1 Tag, oder, ich glaube, alles, was niedriger dann eine ganze Woche (oder niedriger ist dann 6 Tage, wenn Sie erlaubt Teiltöne).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top