Ich muss Werktage vom aktuellen Datum abziehen .
Ich habe derzeit Code, der immer am letzten Geschäftstag ausgeführt werden muss. Das mag heute sein, wenn wir Montag bis Freitag sind, aber wenn es Samstag oder Sonntag ist, muss ich es auf den Freitag vor dem Wochenende zurücksetzen. Ich habe derzeit einen ziemlich klobigen Code, um dies zu tun:
lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) == 5: #if it's Saturday
lastBusDay = lastBusDay - datetime.timedelta(days = 1) #then make it Friday
elif datetime.date.weekday(lastBusDay) == 6: #if it's Sunday
lastBusDay = lastBusDay - datetime.timedelta(days = 2); #then make it Friday
Gibt es einen besseren Weg?
Kann ich timedelta anweisen, beispielsweise an Wochentagen anstatt an Kalendertagen zu arbeiten?
Antworten:
Benutze Pandas!
import datetime # BDay is business day, not birthday... from pandas.tseries.offsets import BDay today = datetime.datetime.today() print(today - BDay(4))
Da heute Donnerstag, der 26. September, ist, erhalten Sie eine Ausgabe von:
datetime.datetime(2013, 9, 20, 14, 8, 4, 89761)
quelle
Es scheint mehrere Optionen zu geben, wenn Sie zusätzliche Bibliotheken installieren möchten.
Dieser Beitrag beschreibt eine Möglichkeit, Arbeitstage mit dateutil zu definieren .
http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-09/3758.html
Mit BusinessHours können Sie Ihre Liste der Feiertage usw. individuell definieren, um festzulegen, wann Ihre Arbeitszeiten (und damit auch die Arbeitstage) sind.
http://pypi.python.org/pypi/BusinessHours/
quelle
self.worktiming[1]
(fehlendes Selbst ) und Zeile 51 lesen sollteextradays
(fehlendes s ). Der Quellcode selbst sieht ziemlich schlecht aus, mit Semikolons, die überall verteilt sind.Vielleicht könnte dieser Code helfen:
lastBusDay = datetime.datetime.today() shift = datetime.timedelta(max(1,(lastBusDay.weekday() + 6) % 7 - 3)) lastBusDay = lastBusDay - shift
Die Idee ist, dass Sie montags 3 Tage zurückgehen müssen, sonntags 2 und an jedem anderen Tag 1.
Die Aussage
(lastBusDay.weekday() + 6) % 7
basiert nur auf dem Montag von 0 bis 6.Ich weiß wirklich nicht, ob dies in Bezug auf die Leistung besser sein wird.
quelle
Wenn Sie sowohl US-Feiertage als auch Wochenenden überspringen möchten, hat dies bei mir funktioniert (mit Pandas 0.23.3):
import pandas as pd from pandas.tseries.holiday import USFederalHolidayCalendar from pandas.tseries.offsets import CustomBusinessDay US_BUSINESS_DAY = CustomBusinessDay(calendar=USFederalHolidayCalendar()) july_5 = pd.datetime(2018, 7, 5) result = july_5 - 2 * US_BUSINESS_DAY # 2018-7-2
Um in ein Python-Datumsobjekt zu konvertieren, habe ich Folgendes getan:
quelle
DISCLAMER: Ich bin der Autor ...
Ich habe ein Paket geschrieben, das genau dies tut, Berechnungen von Geschäftsterminen. Sie können benutzerdefinierte Wochenspezifikationen und Feiertage verwenden.
Ich hatte genau dieses Problem bei der Arbeit mit Finanzdaten und fand keine der verfügbaren Lösungen besonders einfach, also schrieb ich eine.
Hoffe das ist nützlich für andere Leute.
https://pypi.python.org/pypi/business_calendar/
quelle
timeboard
Paket macht das.Angenommen, Ihr Datum ist der 04. September 2017. Obwohl es ein Montag war, war es ein Feiertag in den USA (der Tag der Arbeit). Der letzte Geschäftstag war also Freitag, der 1. September.
>>> import timeboard.calendars.US as US >>> clnd = US.Weekly8x5() >>> clnd('04 Sep 2017').rollback().to_timestamp().date() datetime.date(2017, 9, 1)
In Großbritannien war der 04. September 2017 der reguläre Geschäftstag, daher war der letzte Geschäftstag selbst.
>>> import timeboard.calendars.UK as UK >>> clnd = UK.Weekly8x5() >>> clnd('04 Sep 2017').rollback().to_timestamp().date() datetime.date(2017, 9, 4)
HAFTUNGSAUSSCHLUSS: Ich bin der Autor von Timeboard.
quelle
Dies gibt einen Generator von Arbeitstagen, natürlich ohne Feiertage, Stopp ist datetime.datetime Objekt. Wenn Sie Urlaub brauchen, machen Sie einfach ein zusätzliches Argument mit der Liste der Feiertage und überprüfen Sie mit 'IFology' ;-)
def workingdays(stop, start=datetime.date.today()): while start != stop: if start.weekday() < 5: yield start start += datetime.timedelta(1)
Später können Sie sie wie zählen
workdays = workingdays(datetime.datetime(2015, 8, 8)) len(list(workdays))
quelle
Wenn jemand nach einer Lösung für Feiertage sucht (ohne eine riesige Bibliothek wie Pandas), probieren Sie seine Funktionen aus:
import holidays import datetime def previous_working_day(check_day_, holidays=holidays.US()): offset = max(1, (check_day_.weekday() + 6) % 7 - 3) most_recent = check_day_ - datetime.timedelta(offset) if most_recent not in holidays: return most_recent else: return previous_working_day(most_recent, holidays) check_day = datetime.date(2020, 12, 28) previous_working_day(check_day)
welche produzieren:
datetime.date(2020, 12, 24)
quelle
Warum versuchst du nicht so etwas wie:
lastBusDay = datetime.datetime.today() if datetime.date.weekday(lastBusDay) not in range(0,5): lastBusDay = 5
quelle
def getNthBusinessDay(startDate, businessDaysInBetween): currentDate = startDate daysToAdd = businessDaysInBetween while daysToAdd > 0: currentDate += relativedelta(days=1) day = currentDate.weekday() if day < 5: daysToAdd -= 1 return currentDate
quelle
eine andere vereinfachende Version
lastBusDay = datetime.datetime.today() wk_day = datetime.date.weekday(lastBusDay) if wk_day > 4: #if it's Saturday or Sunday lastBusDay = lastBusDay - datetime.timedelta(days = wk_day-4) #then make it Friday
quelle
Lösung unabhängig von unterschiedlichen Gerichtsbarkeiten mit unterschiedlichen Feiertagen:
Wenn Sie die richtige ID in einer Tabelle finden müssen, können Sie dieses Snippet verwenden. Das Tabellenmodell ist ein SQLalchemiemodell, und die zu suchenden Daten befinden sich am Feldtag.
def last_relevant_date(db: Session, given_date: date) -> int: available_days = (db.query(Table.id, Table.day) .order_by(desc(Table.day)) .limit(100).all()) close_dates = pd.DataFrame(available_days) close_dates['delta'] = close_dates['day'] - given_date past_dates = (close_dates .loc[close_dates['delta'] < pd.Timedelta(0, unit='d')]) table_id = int(past_dates.loc[past_dates['delta'].idxmax()]['id']) return table_id
Dies ist keine Lösung, die ich empfehlen würde, wenn Sie in großen Mengen konvertieren müssen. Es ist ziemlich allgemein und teuer, da Sie keine Joins verwenden. Darüber hinaus wird davon ausgegangen, dass Sie einen relevanten Tag haben, der einer der 100 letzten Tage in der Modelltabelle ist. Es werden also Dateneingaben behandelt, die unterschiedliche Daten haben können.
quelle