-2

Basically I am looking for some kind of method to calculate the business the day before yesterday since I have to run a t-2 query without any manual interference in the datetime variable:

In a nutshell:

27.05.21 -> 25.05.21

Today's date is a dynamic variable changing every day of course and you should consider weekends e.g. 31.05.21 -> 27.05.21

I worked myself off on the "get the last business day method" to modify it...

today = datetime.today()
offset = max(1, (today. weekday() + 6) % 7 - 3)
timedelta = datetime. timedelta(offset)
most_recent = today - timedelta
print(most_recent)

...but I failed miserably and is not worth to mention here.

Any help would be highly appreciated!

Thanks a lot!

Ciao R

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
RMNB
  • 13
  • 2
  • Please detail the problem with your code. I don't see it. A simple test loop for the week of 20-27 May shows the correct result for each day. – Prune May 26 '21 at 21:56
  • 2
    If you need to take into account holidays this code is going to be a lot more complex. – Mark Ransom May 26 '21 at 21:59
  • this code has to run every day and is triggered by jenkins via git. 20-27 may (and so on...) was just an example. So the solution must run every day starting from today and should through the business day as of the day before yesterday which means today = 27.05. -> output: 25.05. Holidays shouldnt be taken in account. – RMNB May 27 '21 at 00:17
  • I wonder why people downvote this question :| This is an interesting problem. Not related to this question but for holidays, it's hard to take into account holidays since it depends on the policy of each country. To account for holidays, we should have a database instead. – Tuan Chau May 27 '21 at 00:45

2 Answers2

0

You can use pandas.tseries.offsets.BusinessDay (this only excludes Saturdays and Sundays).

from datetime import datetime
import pandas as pd

dates = ['24.05.21', '25.05.21', '26.05.21']

def offset(date, offset, date_format='%d.%m.%y'):
    return (datetime.strptime(date, date_format) + pd.tseries.offsets.BusinessDay(offset)).strftime(date_format)

for date in dates:
    print('if today =', date, 'the expected result is', offset(date, -2))

output:

if today = 24.05.21 the expected result is 20.05.21
if today = 25.05.21 the expected result is 21.05.21
if today = 26.05.21 the expected result is 24.05.21

Here's a version without pandas:

from datetime import datetime, timedelta

dates = ['24.05.21', '25.05.21', '26.05.21']

def offset(date, offset, date_format='%d.%m.%y'):
    # adds offset
    output = datetime.strptime(date, date_format) + timedelta(days=offset)
    # adds more offset if output's weekday is Saturday or Sunday
    output += timedelta(days=(output.isoweekday() > 5) * offset)
    # returns output
    return output.strftime(date_format)

for date in dates:
    print('if today =', date, 'the expected result is', offset(date, -2))
Gusti Adli
  • 1,225
  • 4
  • 13
  • Hi thanks forcthe reply! The issue I see with your code is the dates list since this code hast fly automatically each day every day. Since the dates in the dates list is hardcoded this wont work for me. – RMNB May 27 '21 at 00:11
  • The hardcoded dates are examples. But the basic idea is in the `offset()` function. You can use `(datetime.datetime.now() + pd.tseries.offsets.BusinessDay(-2)).date()` to get the exact result you are looking for. – Gusti Adli May 27 '21 at 01:13
0

I think we can make the code simple by predefined how many days we need to shift for the target day. For example, if the target day is Monday or Tuesday, we shift 4 days, otherwise, we shift 2 days for Wednesday to Saturday, 3 days for Sunday.

Code:

import datetime

SHIFT_DAY_MAP = {
    0: 4,
    1: 4,
    2: 2,
    3: 2,
    4: 2,
    5: 2,  # Sat.
    6: 3  # Sun.
}


def get_two_business_day_before(date: datetime.datetime):
    weekday = date.weekday()
    shift_days = SHIFT_DAY_MAP[weekday]
    timedelta = datetime.timedelta(days=shift_days)
    return date - timedelta

Test:

for i in range(7):
    d = datetime.datetime(2021, 5, 10 + i)
    print(d.date(), "->", get_two_business_day_before(d).date())

Result:

2021-05-10 -> 2021-05-06
2021-05-11 -> 2021-05-07
2021-05-12 -> 2021-05-10
2021-05-13 -> 2021-05-11
2021-05-14 -> 2021-05-12
2021-05-15 -> 2021-05-13
2021-05-16 -> 2021-05-13

Note: I assume the desirable shift days for weekends are 2 for Sat and 3 for Sun since your requirement does not mention it.

Tuan Chau
  • 1,243
  • 1
  • 16
  • 30