Reputation: 1386
I need to implement a conditional break which uses business days. I have a class with a DateField
, and if that date is less than 5 business days in the future, something (action a
) happens, else b
happens. How can I determine the number of business days between two objects?
Obviously I'll need to calculate what 5 business days from today is. Finding 5 days in the future would be easy, using a simple time-delta, but to account for business days, it gets more complicated. I think I can safely ignore holidays for now (it's not the best case, but I think I can make due with just having Business days be Monday-Friday). Can anyone give me some guidance as to how I could do something like: target = today + 5 business_days
?
Thanks
Upvotes: 2
Views: 2849
Reputation: 6891
This Example is when you are making a django project as an API
You can get business days with Numpy which uses SCIPY(check for more details)
You will have to install numpy
through pip
pip install numpy
pip3 install numpy
In models.py
add depending on where you want to put your property method :
class WorkingDay(models.Model):
# YY-MM-DD
start = models.DateField(null=True, verbose_name="start")
end = models.DateField(null=True, verbose_name="end")
@property
def workdays(self):
total = np.busday_count(self.start, self.end)
return total
Then in your serializers.py
you might have something like this.
class WorkingDaySerializer(serializers.ModelSerializer):
workdays = serializers.IntegerField(read_only=True)
class Meta:
model = WorkingDay
fields = '__all__'
read_only_fields = ['workdays']
In your views you might do something like this.
class WorkingDayAPI(APIView):
"""
{ "start":"2018-01-01",
"end":"2018-05-01"
}
GET work days between dates
"""
serializer_class = WorkingDaySerializer
def get(self, request, format=None):
business_days = WorkingDay.objects.all()
serializer = WorkingDaySerializer(business_days, many=True)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
start = request.data.get('start')
end = request.data.get('end')
# bizdays = request.data.get('bizdays')
business_days = WorkingDay.objects.create(**request.data)
business_days.start = start
business_days.end = end
business_days.workdays = workdays
business_days.save()
serializer = WorkingDaySerializer(business_days)
return Response(serializer.data, status=status.HTTP_201_CREATED)
Upvotes: 0
Reputation: 11888
Here's a generic solution, even though your case is embarrassingly simple ;P
from datetime import timedelta, date
def add_business_days(from_date, number_of_days):
to_date = from_date
while number_of_days:
to_date += timedelta(1)
if to_date.weekday() < 5: # i.e. is not saturday or sunday
number_of_days -= 1
return to_date
And the result.
>>> date.today()
datetime.date(2013, 7, 25)
>>> add_business_days(date.today(), 6)
datetime.date(2013, 8, 2)
Bonus marks if you check whether a date falls on a holiday in the if statement.
Upvotes: 4