Adding 6 business days - python-2.7

I have a function that will calculate 6 days, it works, and it's wonderful and all, but I need a way to skip Saturday and Sunday. How can I fix this function in order to have it skip Saturday and Sunday?
def calc_bus_day(start_day):
if start_day.isoweekday() in range(1, 5):
shift = 6
returnDate = start_day + datetime.timedelta(days=shift)
if returnDate.isoweekday() == 0:
return "{:%m-%d-Y}".format(returnDate + datetime.timedelta(days=1))
elif returnDate.isoweekday() == 5:
return "{:%m-%d-%Y}".format(returnDate + datetime.timedelta(days=2))
else:
return "{:%m-%d-%Y}".format(returnDate)

As shifting for 6 days always includes shifting over a weekend, you can shift for 8 days (6 days + Saturday and Sunday):
def calc_bus_day(start_day):
if start_day.isoweekday() in range(1, 5):
shift = 8
< your code >

You can use this code that I use. The attempt it is add not just 6 days, but any number of days.
from datetime import datetime, timedelta, date
def getNextBusinessDays(date, num):
for i in range(0, num):
date = getNextBusinessDay(date)
return date
def getNextBusinessDay(fromDate):
nextBuinessDate = datetime.strptime(fromDate, "%Y-%m-%d")
nextBuinessDate = nextBuinessDate + timedelta(days=1)
if date.weekday(nextBuinessDate) not in range(0, 5):
nextBuinessDate = nextBuinessDate + timedelta(days=1)
if date.weekday(nextBuinessDate) not in range(0, 5):
nextBuinessDate = nextBuinessDate + timedelta(days=1)
return nextBuinessDate.strftime('%Y-%m-%d')
For example getNextBusinessDays('2016-10-20', 6) will produce "2016-10-28"

Related

How to get the number of Days in a Specific Month between Two Dates in Python

I have two date fields campaign_start_date and campaign_end_date. I want to count the number of days in each month that comes in-between the campaign_start_date and campaign_end_date.
eg:
campaign_start_date = September 7 2017
campaign_end_date = November 6 2017
The solution should be :
Total No:of days = 61 days
No: of months = 3 months
Month 1 = 9/7/2017 to 9/30/2017
Month 2 = 10/1/2017 to 10/31/2017
Month 3 = 11/1/2017 to 11/6/2017
No:of days in Month 1 = 24 days
No:of days in Month 2 = 31 days
No:of days in Month 3 = 6 days
How can I achieve this using Python?
So far I have achieved:
#api.multi
def print_date(self):
start_date = datetime.strptime(self.start_date, "%Y-%m-%d %H:%M:%S")
end_date = datetime.strptime(self.end_date, "%Y-%m-%d %H:%M:%S")
campaign_start_date = date(start_date.year,start_date.month,start_date.day)
campaign_end_date = date(end_date.year,end_date.month,end_date.day)
duration = (campaign_end_date-campaign_start_date).days
return True
Calculate the duration in days:
from datetime import date
campaign_start_date = date(2017, 9, 7)
campaign_end_date = date(2017, 10, 6)
duration = (campaign_end_date-campaign_start_date).days
print campaign_start_date, campaign_end_date, duration
Some hints for further calculations:
import calendar
campaign_end_month_start = campaign_end_date.replace(day=1)
days_in_month_campaign_end = (campaign_end_date - campaign_end_month_start).days + 1
range_startmonth = calendar.monthrange(campaign_start_date.year, campaign_start_date.month)
campaign_start_month_ends = campaign_start_date.replace(day=range_startmonth[1])
days_in_month_campaign_begins = (campaign_start_month_ends - campaign_start_date).days
This way you can calculate the number of days in each month of the campaign (keep in mind to check if campaign_end_date is in another month than campaign_start_date
For calculations you can also access the fields of a date, e.g.
campaign_start_date.day
campaign_start_date.month
campaign_start_date.year
To calculate the number of involved month in your campaign and to get a list of the month to calculate the duration per month you can use this (based on the answer of m.antkowicz in Python: get all months in range?). It's important to set the day to 1 (current = current.replace(day=1)) before and inside the loop, otherwise you skip a month when your startdate is 31st of a month and the next month is shorter than 31 days or if you have a longer period:
from datetime import date, datetime, timedelta
current = campaign_start_date
result = [current]
current = current.replace(day=1)
while current <= campaign_end_date:
current += timedelta(days=32)
current = current.replace(day=1)
result.append(datetime(current.year, current.month, 1))
print result, len(result)
which prints (when you use current.strftime('%Y-%m-%d'):
['2017-09-07', '2017-10-01', '2017-11-01'] 3
now you can loop over the result list and calculate the number of days per months:
durations= []
for curr in result:
curr_range = calendar.monthrange(curr.year, curr.month)
curr_duration = (curr_range[1] - curr.day)+1
if (curr.month < campaign_end_date.month):
durations.append(curr_duration)
else:
durations.append(campaign_end_date.day)
print durations
which gives you the desired "No:of days in Month x" as a list:
[24, 31, 6]
This is the robust solution which takes care of dates from different years.
def get_months_and_durations(start_date,end_date):
current = start_date
result = [current]
current = current.replace(day=1)
while current <= end_date:
current += timedelta(days=32)
current = current.replace(day=1)
result.append(datetime(current.year, current.month, 1).date())
durations= []
for curr in result[:-1]:
curr_range = calendar.monthrange(curr.year, curr.month)
curr_duration = (curr_range[1] - curr.day)+1
if ((curr.month == end_date.month) & (curr.year == end_date.year)):
durations.append(end_date.day)
else:
durations.append(curr_duration)
return result[:-1],durations

date format cannot convert in data format

I am trying to create an application where it pulls the information from website using python and I am using datetime formats.
def constructYFURL(ticker,start_date,end_date,freq):
start_date = datetime.strptime(start_date,"%Y-%m-%d").date()
end_date = datetime.strptime(end_date,"%Y-%m-%d").date()
s=ticker.replace("^","%5E")
if start_date.month-1<10:
a="0"+str(start_date.month-1)
else:
a=str(start_date.month-1)
# Also the month always has 2 digits
b=str(start_date.day)
c=str(start_date.year)
if end_date.month - 1 < 10:
d = "0" + str(end_date.month - 1)
else:
d = str(end_date.month - 1)
e=str(end_date.day)
f=str(end_date.year)
`enter code here`g=freq
yfURL = "http://real-chart.finance.yahoo.com/table.csv? s="+s+"&a="+a+"&b="+b+"&c="+c+"&d="+d+"&e="+e+"&f="+f+"&g="+g+"&ignore=.csv"
return yfURL
from download import constructYFURL
ticker = "AAPL"
start_date = "2016-01-01"
end_date = " 2017-03-06"
freq = "d"
yfURL = constructYFURL(ticker,start_date,end_date,freq)
print yfURL
I am getting a following error saying:
ValueError: time data ' 2017-03-06' does not match format '%Y-%m-%d'
You have an extra leading space in:
end_date = " 2017-03-06"
remove it and the error you're getting goes away and the program runs
Better formatted code:
def constructYFURL(ticker,start_date,end_date,freq):
start_date = datetime.strptime(start_date,"%Y-%m-%d").date()
end_date = datetime.strptime(end_date,"%Y-%m-%d").date()
s=ticker.replace("^","%5E")
if start_date.month-1<10:
a="0"+str(start_date.month-1)
else:
a=str(start_date.month-1)
# Also the month always has 2 digits
b=str(start_date.day)
c=str(start_date.year)
if end_date.month - 1 < 10:
d = "0" + str(end_date.month - 1)
else:
d = str(end_date.month - 1)
e=str(end_date.day)
f=str(end_date.year)
g=freq
yfURL = "http://real-chart.finance.yahoo.com/table.csv? s="+s+"&a="+a+"&b="+b+"&c="+c+"&d="+d+"&e="+e+"&f="+f+"&g="+g+"&ignore=.csv"
return yfURL
ticker = "AAPL"
start_date = "2016-01-01"
end_date = "2017-03-06"
freq = "d"
yfURL = constructYFURL(ticker,start_date,end_date,freq)
print yfURL

Get First Date and Last Date of Current Quarter in Python?

How can i get the Current Quarter year and then First Date and last Date of Current Quarter Year in Python?
i want by importing datetime
import datetime
People look into Stack overflow need straight forward answer and which should be very simple. Which ever link you provided it having lot of Comments. SO, users has to go through all the comments to find correct answer. I am writing simple and straight forward answer.
I believe that none of the current answers are still valid in Python 3, so since this is the top hit in google for first and last day of quarter, I will provide a solution that works in Python 3 (mostly Ahmet's with // instead of /):
from datetime import date as date_class
from datetime import timedelta, datetime
def get_quarter(p_date: date_class) -> int:
return (p_date.month - 1) // 3 + 1
def get_first_day_of_the_quarter(p_date: date_class):
return datetime(p_date.year, 3 * ((p_date.month - 1) // 3) + 1, 1)
def get_last_day_of_the_quarter(p_date: date_class):
quarter = get_quarter(p_date)
return datetime(p_date.year + 3 * quarter // 12, 3 * quarter % 12 + 1, 1) + timedelta(days=-1)
assert get_quarter(datetime(year=2021, month=10, day=5).date()) == 4
assert get_quarter(datetime(year=2020, month=9, day=25).date()) == 3
assert get_quarter(datetime(year=2020, month=12, day=11).date()) == 4
assert get_quarter(datetime(year=2020, month=1, day=2).date()) == 1
assert get_first_day_of_the_quarter(datetime(2020, 10, 5).date()) == datetime(2020, 10, 1)
assert get_first_day_of_the_quarter(datetime(2020, 9, 25).date()) == datetime(2020, 7, 1)
assert get_first_day_of_the_quarter(datetime(2020, 12, 11).date()) == datetime(2020, 10, 1)
assert get_first_day_of_the_quarter(datetime(2020, 1, 2).date()) == datetime(2020, 1, 1)
assert get_last_day_of_the_quarter(datetime(2020, 10, 5).date()) == datetime(2020, 12, 31)
assert get_last_day_of_the_quarter(datetime(2020, 9, 25).date()) == datetime(2020, 9, 30)
assert get_last_day_of_the_quarter(datetime(2020, 12, 11).date()) == datetime(2020, 12, 31)
assert get_last_day_of_the_quarter(datetime(2020, 1, 2).date()) == datetime(2020, 3, 31)
assert get_last_day_of_the_quarter(datetime(2020, 5, 6).date()) == datetime(2020, 6, 30)
Having the first day is the same with #Karishh's solution. But, for the last date, Python2.7 causes a problem for fourth quarter. Because 12+1=13 and datetime does not accept 13 as a month. So you need to do some tricks to handle it.
import datetime
def get_quarter(date):
return (date.month - 1) / 3 + 1
def get_first_day_of_the_quarter(date):
quarter = get_quarter(date)
return datetime.datetime(date.year, 3 * quarter - 2, 1)
def get_last_day_of_the_quarter(date):
quarter = get_quarter(date)
month = 3 * quarter
remaining = month / 12
return datetime.datetime(date.year + remaining, month % 12 + 1, 1) + datetime.timedelta(days=-1)
Any how i found some simple solution in c# and converted it into python,
from datetime import datetime,timedelta
current_date=datetime.now()
currQuarter = (current_date.month - 1) / 3 + 1
dtFirstDay = datetime(current_date.year, 3 * currQuarter - 2, 1)
dtLastDay = datetime(current_date.year, 3 * currQuarter + 1, 1) + timedelta(days=-1)
Here's a one/two liner to get the start/end date of the current quarter.
from datetime import datetime
import math
from dateutil.relativedelta import relativedelta # requires python-dateutil
start_of_quarter = datetime(year=datetime.now().year, month=((math.floor(((datetime.now().month - 1) / 3) + 1) - 1) * 3) + 1, day=1)
end_of_quarter = start_of_quarter + relativedelta(months=3, seconds=-1)
pendulum has a much more intuitive implementation.
import pendulum
dt = pendulum.datetime(2021, 3, 23)
print(dt.first_of('quarter'))
print(dt.last_of('quarter'))
2021-01-01T00:00:00+00:00
2021-03-31T00:00:00+00:00
Building off of the answer from Krishh, but addressing several issues found:
calculating last day in Quarter 4
Wasae Shoaib's comment about raising a ValueError
TypeError with a float being passed instead of an integer
Using relativedeta instead and shifting the correctly calculated start date by three months, we end up with a much more reliable way to get at the quarter end date.
from datetime import datetime
from dateutil.relativedelta import relativedelta
current_date = datetime.now()
currQuarter = int((current_date.month - 1) / 3 + 1)
dtFirstDay = datetime(current_date.year, 3 * currQuarter - 2, 1)
dtLastDay = dtFirstDay + relativedelta(months=3, days=-1)
I did of a lot of tests to find the solution that fit my need and I will be happy if it helps someone else :
datval = fields.date.today()
if datval.month < 4 :
self.start_date = fields.date.today().replace(month=10, day=1)
self.end_date = fields.date.today().replace(month=12, day=31)
elif datval.month < 7 :
self.start_date = fields.date.today().replace(month=1, day=1)
self.end_date = fields.date.today().replace(month=3, day=31)
elif datval.month < 10 :
self.start_date = fields.date.today().replace(month=4, day=1)
self.end_date = fields.date.today().replace(month=6, day=30)
else :
self.start_date = fields.date.today().replace(month=7, day=1)
self.end_date = fields.date.today().replace(month=9, day=30)
Get start and end points for: week, month, quarter and year
https://gist.github.com/dejurin/236b398dc4b8064685702a27a3df612b
from datetime import date
from dateutil.relativedelta import relativedelta
def start_end_day(sunmon: bool = True):
today = date.today()
curr_quarter = int((today.month - 1) / 3 + 1)
dayofweek = [today.weekday(),today.isoweekday()][sunmon]
week_start = today - relativedelta(days=dayofweek)
week_end = week_start + relativedelta(days=6)
month_start = date(today.year,today.month, 1)
month_end = month_start + relativedelta(months=1, days=-1)
quarter_start = date(today.year, 3 * curr_quarter - 2, 1)
quarter_end = quarter_start + relativedelta(months=3, days=-1)
year_start = date(today.year, 1, 1)
year_end = year_start + relativedelta(years=1, days=-1)
return ((week_start,week_end),(month_start,month_end),(quarter_start,quarter_end),(year_start,year_end))
"""
Current date: 18/02/2022
"""
"""
((datetime.date(2022, 2, 13), datetime.date(2022, 2, 19)),
(datetime.date(2022, 2, 1), datetime.date(2022, 2, 28)),
(datetime.datetime(2022, 1, 1, 0, 0), datetime.datetime(2022, 3, 31, 0, 0))
(datetime.date(2022, 1, 1), datetime.date(2022, 12, 31)))
"""

Django: Total birthdays each day for the next 30 days

I've got a model similar to this:
class Person(models.Model):
name = models.CharField(max_length=40)
birthday = DateTimeField() # their next birthday
I would like to get a list of the total birthdays for each day for the next 30 days. So for example, the list would look like this:
[[9, 0], [10, 3], [11, 1], [12, 1], [13, 5], ... #30 entries in list
Each list entry in the list is a date number followed by the number of birthdays on that day. So for example on the 9th of May there are 0 birthdays.
UPDATES
My db is sqlite3 - will be moving to postgres in the future.
from django.db.models import Count
import datetime
today = datetime.date.today()
thirty_days = today + datetime.timedelta(days=30)
birthdays = dict(Person.objects.filter(
birthday__range=[today, thirty_days]
).values_list('birthday').annotate(Count('birthday')))
for day in range(30):
date = today + datetime.timedelta(day)
print "[%s, %s]" % (date, birthdays.get(date, 0))
I would get the list of days and birthday count this way:
from datetime import date, timedelta
today = date.today()
thirty_days = today + timedelta(days=30)
# get everyone with a birthday
people = Person.objects.filter(birthday__range=[today, thirty_days])
birthday_counts = []
for date in [today + timedelta(x) for x in range(30)]:
# use filter to get only birthdays on given date's day, use len to get total
birthdays = [date.day, len(filter(lambda x: x.birthday.day == date.day, people))]
birthday_counts.append(birthdays)
Something like this --
from datetime import date, timedelta
class Person(models.Model):
name = models.CharField(max_length=40)
birthday = models.DateField()
#staticmethod
def upcoming_birthdays(days=30):
today = date.today()
where = 'DATE_ADD(birthday, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR) BETWEEN DATE(NOW()) AND DATE_ADD(NOW(), INTERVAL %S DAY)'
birthdays = Person.objects.extra(where=where, params=[days]).values_list('birthday', flat=True)
data = []
for offset in range(0, days):
i = 0
d = today + timedelta(days=offset)
for b in birthdays:
if b.day == d.day and b.month == d.month:
i += 1
data.append((d.day, i))
return data
print Person.upcoming_birthdays()
(Queryset of people with a birthday in the next X days)
Found cool solution for this!
For me it works!
from datetime import datetime, timedelta
import operator
from django.db.models import Q
def birthdays_within(days):
now = datetime.now()
then = now + timedelta(days)
# Build the list of month/day tuples.
monthdays = [(now.month, now.day)]
while now <= then:
monthdays.append((now.month, now.day))
now += timedelta(days=1)
# Tranform each into queryset keyword args.
monthdays = (dict(zip(("birthday__month", "birthday__day"), t))
for t in monthdays)
# Compose the djano.db.models.Q objects together for a single query.
query = reduce(operator.or_, (Q(**d) for d in monthdays))
# Run the query.
return Person.objects.filter(query)
But it get a list of persons that have a birthday in date range. You should change a bit.

Numerology with Python And Django

i have a function that give me the result that im expecting in console mode, but if i try to use the function with Django, the page never load and just have a loop calculating and never end.
Any idea ?
*sorry with my english
Console function (WORK GREAT):
def sum_digitos(n):
sum = 0;
while n != 0:
sum += n % 10
n /= 10
if sum > 9:
x = str(sum)
y =list(x)
sum = int(y[0]) + int(y[1])
return sum
print sum_digitos(2461978)
Django views:
def Calcular(request):
if request.method == 'POST':
form = NumerologiaForm(request.POST)
if form.is_valid():
sum = 0;
ano = str(request.POST['fecha_year'])
mes = str(request.POST['fecha_month'])
dia = str(request.POST['fecha_day'])
data = dia + mes + ano
fecha = int(data)
while fecha != 0:
f = fecha
sum += f % 10
f /= 10
if sum > 9:
x = str(sum)
y =list(x)
sum = int(y[0]) + int(y[1])
resultado = get_object_or_404(Numero,numero = sum)
return HttpResponseRedirect(resultado.get_absolute_url())
else:
form = NumerologiaForm()
return render_to_response('numerologiaForm.html',{'form':form})
Try:
f = fecha
while f!= 0:
sum += f % 10
f /= 10
if sum > 9:
x = str(sum)
y =list(x)
sum = int(y[0]) + int(y[1])
It seems you were changing f, but checking fecha for the looping.
Sanjay's answer is the correct one, and I recommend it. I just wanted to ask why you didn't just do:
from numerology import sum_digitos
def Calcular(request):
# In your code, you return HttpResponseRedirect using a nonexistent
# "resultado" variable if the form is not valid. This will raise an
# exception. I think you meant to indent "return Http..." one step more.
if request.method == 'POST':
form = NumerologiaForm(request.POST)
else:
form = NumerologiaForm()
# "or..." part of next line not needed if form.is_valid() returns
# False for a blank form.
if not form.is_valid() or form == NumerologiaForm():
return render_to_response('numerologiaForm.html', {'form': form})
ano = str(request.POST['fecha_year'])
mes = str(request.POST['fecha_month'])
dia = str(request.POST['fecha_day'])
resultado = get_object_or_404(Numero,
numero=sum_digitos(int(dia + mes + ano)))
return HttpResponseRedirect(resultado.get_absolute_url())
You had a working function in Python already... why not just import it and use it?
There's no need to go to all that work to sum the digits in that number, because the sum of the digits is num % 9. If num % 9 is zero, then the actual sum of digits is 9.
By changing your method to
def sum_digitos(n):
sum_ = n % 9
return sum_ if sum_ != 0 else 9
You will completely avoid whatever issue was happening inside your original method.
You don't say what the rest of your environment is like, but you should be using f //= 10 to ensure that you're performing integer division.