Python에서 가장 최근의 전 영업일


81

현재 날짜에서 영업일 을 빼야 합니다.

현재 가장 최근 영업일에 항상 실행해야하는 코드가 있습니다. 월요일부터 금요일까지라면 오늘 일 수 있지만 토요일이나 일요일이면 주말 전의 금요일로 다시 설정해야합니다. 나는 현재 이것을하기위한 꽤 투박한 코드가있다.

 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

더 좋은 방법이 있습니까?

예를 들어 timedelta에게 달력 일이 아닌 평일에 일하도록 말할 수 있습니까?


7
휴일은 어떻습니까?
SLaks

다음은 도움이 될만한 dzzone의 스 니펫입니다. snippets.dzone.com/posts/show/9173
David Underhill

예, 저는 이미 그것들을 처리하고 있습니다. 제 데이터베이스는 평일에 해당하는 한 항상 휴일을 채 웁니다. 그러나 나는 일반적으로 휴일도 문제라는 데 동의합니다. 나는 공상을 시작하고 sckits.timeseries를 사용할 수 있지만 실제로는 더 간단한 것을 원합니다.
Thomas Browne

1
안녕하세요, 파티에 늦었어요. 죄송합니다. OP가 할 수있는 한 가지 더 간단한 일은 토요일과 일요일을 따로 확인하는 대신 datetime.date.weekday (lastBusDay)> = 5인지 확인하는 것입니다. 하지만 그래 .. 어쨌든 아래에 다른 더 나은 대답이 있습니다.
tagoma

답변:


142

판다를 사용하세요!

import datetime
# BDay is business day, not birthday...
from pandas.tseries.offsets import BDay

today = datetime.datetime.today()
print(today - BDay(4))

오늘은 9 월 26 일 목요일이므로 다음과 같은 결과를 얻을 수 있습니다.

datetime.datetime(2013, 9, 20, 14, 8, 4, 89761)

2
좋은. 오늘은 정답입니다. Q를 물었을 때 팬더는 여전히 약간 불완전했습니다.
Thomas Browne 2013 년

6
가장 최근 팬더 릴리스 (0.14.0)가 너무 휴일 달력 지원
fantabolous

1
Pandas를 설치하면 vps에 233M이 추가됩니다. 그래서 저는 베어 본 휠을 재발 명했습니다.
Stuart Gathman


13

추가 라이브러리를 설치하려면 몇 가지 옵션이있는 것 같습니다.

이 게시물은 dateutil로 근무일을 정의하는 방법을 설명합니다 .

http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-09/3758.html

BusinessHours를 사용하면 휴일 목록 등을 사용자 정의하여 근무 시간 (및 연장 근무일)을 정의 할 수 있습니다.

http://pypi.python.org/pypi/BusinessHours/


좋은 앨리슨. 불행히도 여전히 간단하지는 않습니다. 나는 당신의 길을 갈 것입니다. 도와 주셔서 감사합니다.
Thomas Browne

2
모든 문화권에서 영업일을 정의하는 것은 표준 라이브러리에 포함될 수있을만큼 간단한 문제 일 것 같지 않습니다.
Alison R.

2
실제로 내 응용 프로그램은 금융 시장이고 이집트와 이스라엘은 일요일에 열려 있으므로 유효한 점입니다.
Thomas Browne

2
누구도 BuinessHours를 사용합니까? 1 분 안에 87 행이 self.worktiming[1](missing self )이고 51 행이 extradays(missing s ) 라는 것을 발견했습니다 . 소스 코드 자체는 세미콜론이 전체에 흩어져있어 매우 열악 해 보입니다.
Pakman

12

미국 공휴일과 주말을 건너 뛰고 싶다면 이것은 나를 위해 일했습니다 (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

파이썬 날짜 객체로 변환하려면 다음을 수행했습니다.

result.to_pydatetime().date()

11

이 코드가 도움이 될 수 있습니다.

lastBusDay = datetime.datetime.today()
shift = datetime.timedelta(max(1,(lastBusDay.weekday() + 6) % 7 - 3))
lastBusDay = lastBusDay - shift

아이디어는 월요일에 3 일, 일요일 2에, 다른 날에는 1로 돌아 가야한다는 것입니다.

진술 (lastBusDay.weekday() + 6) % 7 은 월요일을 0에서 6으로 변경합니다.

이것이 성능면에서 더 나을지 정말 모릅니다.


10

면책 조항 : 저는 저자입니다 ...

나는 정확히 이것을 수행하는 패키지를 작성했습니다. 비즈니스 날짜 계산. 사용자 지정 주 지정 및 공휴일을 사용할 수 있습니다.

재무 데이터로 작업하는 동안이 정확한 문제가 있었고 사용 가능한 솔루션을 특별히 쉽게 찾지 못했기 때문에 하나를 작성했습니다.

이것이 다른 사람들에게 유용하기를 바랍니다.

https://pypi.python.org/pypi/business_calendar/


1
감사합니다. 귀하의 라이브러리는 저에게 완벽하게 작동했습니다. 어쩌면 당신은 당신의 라이브러리 지원 부정적인 일이 당신이 일을 빼려면 당신의 문서에 추가해야하고,이 핍에 최대입니다
guinunez

이것이 귀하에게 연락하는 가장 좋은 방법이 아닐 수도 있다는 것을 알고 있지만 귀하의 business_calendar 모듈에 발생한 문제를보고하고자합니다. 미국 연방 공휴일로 캘린더를 설정했습니다 : [ '2015-01-01', '2015-01-19', '2015-02-16', '2015-05-25', '2015-07-03' , '2015-09-07', '2015-10-12', '2015-11-11', '2015-11-26', '2015-12-25'] 그런 다음 datetime ( 2015, 1, 16, 15, 28, 40) 및 datetime (2015, 1, 23, 11, 58, 0)이지만 일관되게 -1을 반환합니다. 4에서 datetimes 결과에서 h / m / s를 (올바르게) 제거합니다.
Darren Ringer

1
실제로 추가 테스트에서 특정 날짜 비교는 명백한 이유없이 결과를 반환하지 않는 것처럼 차단됩니다. 위의 예에서 datetime (2015, 1, 16)을 datetime (2015, 1, 25)과 비교하려고하면 명시 적으로 휴일을 설정하거나 설정하지 않고 이러한 블록이 생성됩니다. 조사시 이는 date2 매개 변수가 근무일이 아닌 날짜 일 때 발생합니다.
Darren Ringer 2015 년

6

timeboard 패키지는 이것을합니다.

날짜가 2017 년 9 월 4 일이라고 가정합니다. 월요일 임에도 불구하고 미국의 공휴일 (노동절)이었습니다. 따라서 가장 최근 영업일은 9 월 1 일 금요일이었습니다.

>>> import timeboard.calendars.US as US
>>> clnd = US.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 1)

영국에서는 2017 년 9 월 4 일이 정규 영업일 이었으므로 가장 최근 영업일은 그 자체였습니다.

>>> import timeboard.calendars.UK as UK
>>> clnd = UK.Weekly8x5()
>>> clnd('04 Sep 2017').rollback().to_timestamp().date()
datetime.date(2017, 9, 4)

면책 조항 : 저는 타임 보드의 작성자입니다.


4

누군가가 (pandas와 같은 거대한 라이브러리없이) 휴일을 존중하는 솔루션을 찾고 있다면 다음 함수를 시도해보십시오.

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)

생성하는 :

datetime.date(2020, 12, 24)

2

이것은 물론 공휴일없이 근무일의 생성자에게 줄 것이고 stop은 datetime.datetime 객체입니다. 공휴일이 필요한 경우 공휴일 목록과 함께 추가 논의를하고 'IFology'로 확인하십시오 ;-)

def workingdays(stop, start=datetime.date.today()):
    while start != stop:
        if start.weekday() < 5:
            yield start
        start += datetime.timedelta(1)

나중에 다음과 같이 셀 수 있습니다.

workdays = workingdays(datetime.datetime(2015, 8, 8))
len(list(workdays))

0

다음과 같은 것을 시도해보십시오.

lastBusDay = datetime.datetime.today()
if datetime.date.weekday(lastBusDay) not in range(0,5):
    lastBusDay = 5

0
 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 

0

또 다른 단순화 버전

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

0

공휴일이 다른 관할권에 관계없이 솔루션 :

테이블 내에서 올바른 ID를 찾아야하는 경우이 스 니펫을 사용할 수 있습니다. 테이블 모델은 sqlalchemy 모델이며 검색 할 날짜는 필드 데이에 있습니다.

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

이것은 대량으로 변환해야 할 때 권장하는 솔루션이 아닙니다. 조인을 사용하지 않기 때문에 다소 일반적이고 비용이 많이 듭니다. 또한 모델 테이블에서 가장 최근의 100 일 중 하나 인 관련 날짜가 있다고 가정합니다. 따라서 날짜가 다를 수있는 데이터 입력을 처리합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.