Loop through dates except for weekends - python

So I have a script that has date arguments for different functions and I want it to loop through 01-01-2012 to 06-09-2012 not including weekends. Im trying to figure out a way I can use time delta because my script outputs files with the date used in the name of the file for example:
items = (functions.getItems(item,date)
print items
test = sum(abs(l[-1]) for l in items)
total = open('total' +str(datetime.today- datetime.timedelta(1)),'a')
I want timedelta(1) to cycle through each date so that the output file would have the format of total2012-01-01 for the first day and cycle through until it created the file total2012-06-09. Also the date argument for items has the format of MM-DD-YYYY
I thought that I could do this:
sd = 01-01-2012
ed = 06-09-2012
delta = datetime.timedelta(days=1)
diff = 0
while sd != ed
# do functions
# (have output files (datetime.today - datetime.delta(diff))
diff +=1
sd+=delta
So essentially I'm just trying to figure out how can I loop through having the function start with 01-01-2012 and ending with 06-10-2012 excluding weekends. I'm having trouble figuring out how to exclude weekends and how to get it to loop in the proper order
Thanks

Use the datetime.weekday() method. It returns values between zero and six, related to the weekdays. Saturday value is 5 and Sunday value is 6; so, if you skip the operation when these values appear, you skip weekdends:
start = datetime(2012, 1, 1)
end = datetime(2012, 10, 6)
delta = timedelta(days=1)
d = start
diff = 0
weekend = set([5, 6])
while d <= end:
if d.weekday() not in weekend:
diff += 1
d += delta

There is easier way to do this using freq = 'B' for business day frequency.
import pandas as pd
dt = pd.date_range(start=datetime.date.today(), periods=10, freq='B')
dt
which gives you :
DatetimeIndex(['2018-08-13', '2018-08-14', '2018-08-15', '2018-08-16',
'2018-08-17', '2018-08-20', '2018-08-21', '2018-08-22',
'2018-08-23', '2018-08-24'],
dtype='datetime64[ns]', freq='B')
you check name of day also by:
dt.weekday_name
Index(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Monday',
'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
dtype='object')

#brandizzi's answer is more syntactically aesthetic but as an alternative you can use the following
start = datetime(2012, 1, 1)
end = datetime(2012, 10, 6)
delta = timedelta(days=1)
d = start
diff = 0
SATURDAY = 5
while d <= end:
if d.weekday() < SATURDAY:
diff += 1
d += delta

Related

Datetime return dates between weekdays

If today is represented as follows:
todayStr = datetime.today().strftime("%d%m%Y")
todayStr
'09012021'
How do I get a list of values for:
Dates >= last Monday but < Thursday
For example today it would be:
['04012021','05012021','06012021']
Dates >= last Thursday but < Monday
Today it would be:
['07012021','08012021','09012021']
The following code:
import datetime
today = datetime.date.today()
prev_monday = today - datetime.timedelta(days=today.weekday())
dates1 = [(prev_monday + datetime.timedelta(days=d)).strftime("%d%m%Y") for d in range(3)]
dates2 = [(prev_monday + datetime.timedelta(days=d)).strftime("%d%m%Y") for d in range(3, 6)]
print(dates1)
print(dates2)
produces:
['04012021', '05012021', '06012021']
['07012021', '08012021', '09012021']

Last element of list with datetime object

I have 2 "ranges" of datetime objects, defined by a start and stop date.
I want to create a new "range" (start and stop date) for matching days in the first 2 ranges.
Here's what I tried, but I'm having issues with the list: it doens't seem to properly get the last element?
import datetime
#First date range is next week from monday to sunday:
next_week_day = datetime.datetime.now().date() + datetime.timedelta(days=7)
monday = next_week_day - datetime.timedelta(days=next_week_day.weekday())
sunday = monday + datetime.timedelta(days=7)
daterange = [monday + datetime.timedelta(days=x) for x in range(0, (sunday-monday).days)]
#Second daterange can be anything:
start = datetime.date(2020, 8, 2)
end = datetime.date(2020, 9, 25)
daterange_2 = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]
#then I create a list to add matching days to create the new range
date_list = []
for date in daterange:
for date_2 in daterange_2:
if date_2 == date:
date_list.append(date)
#and retrieve first and last day in list
first_date = date_list[0]
second_date = date_list[-1]
print(first_date, second_date)
print(type(first_date), type(second_date))
prints '2020, 9, 24' for second_date instead of '2020, 9, 25'.
What am I missing?
You need to update the ranges of both daterange and daterange_2 to include all the necessary dates:
import datetime
# First date range is next week from monday to sunday:
next_week_day = datetime.datetime.now().date() + datetime.timedelta(days=7)
monday = next_week_day - datetime.timedelta(days=next_week_day.weekday())
sunday = monday + datetime.timedelta(days=7)
daterange = [monday + datetime.timedelta(days=x) for x in range(0, (sunday - monday).days + 1)]
# Second daterange can be anything:
start = datetime.date(2020, 8, 2)
end = datetime.date(2020, 9, 25)
daterange_2 = [start + datetime.timedelta(days=x) for x in range(0, (end - start).days + 1)]
# then I create a list to add matching days to create the new range
date_list = []
for date in daterange:
for date_2 in daterange_2:
if date_2 == date:
date_list.append(date)
# and retrieve first and last day in list
first_date = date_list[0]
second_date = date_list[-1]
print(first_date, second_date)
print(type(first_date), type(second_date))

finding astrology signs according to your month and date, simpler way to do it? instead of 12 if function

if month == 12:
if 0 < date < 23:
return 'SAG'
if 23 <= date < 32:
return 'CAP'
if month == 1:
if 0 < date < 21:
return 'CAP'
if 21 <= date < 32:
return 'AQU'
if month == 2:
if 0 < date < 20:
return 'AQU'
if 20 <= date < 30:
return 'PIS'
if month == 3:
if 0 < date < 21:
return 'PIS'
if 21 <= date < 32:
return 'ARI'
I am looking for a simpler and more effective way of completing my function of finding astrological sign according to month and date, is there a more effective method or is using 12 if loops a must?
You're right to think there's a better way. Use the datetime package. Set up a list of start dates and check the appropriate range for the given date. Since Capricorn spans the calendar year, you'll have two entries for that one:
import datetime
from datetime import date
signs = [ # start date, abbreviation
(date(month=1, day=1), "CAP"),
(date(month=1, day=20), "AQU"),
(date(month=2, day=18), "PIC"),
...
(date(month=12, day=19), "CAP"),
(date(month=12, day=31), "end of year"),
]
Now, you build a date from the given month and year. Iterate through the list, looking for the a given date being greater than the current date, and less than the next one. When you find that entry, you report/return the sign abbreviation.
Does that get you moving?
Dates are always tough to work with and mapping the lunar calendar to the solar calendar present special problems. It becomes easier if you approach it from a days in the year problem instead of a dates problem.
import numpy as np
from datetime import datetime as dt
def getSign(birthDate):
#get day of year of birth
dayOfBirth = (birthDate - dt(birthDate.year, 1, 1)).days
#adjust for leap years
if birthDate.year%4==0 and dayOfBirth > 60:
dayOfBirth -= 1
#build dict of max day for each sign. capricorn is set twice due to straddling of solar year
signs = {20:'Capricorn', 49:'Aquarius', 79:'Pisces', 109:'Aries', 140:'Taurus', 171:'Genini', 203:'Cancer', 234:'Leo', 265:'Virgo', 295:'Libra', 325:'Scorpio', 355:'Sagitarius', 365:'Capricorn'}
#create numpy array of maximum days
daysArray = np.array(list(signs.keys()))
#get sign max days closest to but larger than dayOfBirth
maxDayCount = min(daysArray[daysArray >= dayOfBirth])
return signs[maxDayCount]
>>> getSign(dt(2000, 3, 22))
'Aries'
>>> getSign(dt(2000, 1, 1))
'Capricorn'
>>> getSign(dt(2000, 12, 22))
'Sagitarius'
>>> getSign(dt(2000, 12, 31))
'Capricorn'

Issue with code related to deltatime in python

The following code's aim was to convert a date to corresponding day. I took 2nd October 2017 as the reference and hence proceeded. I don't entirely understand deltatime and guessing the problem might be with how I used it. Hope someone could help me.
import datetime
ans = 'Y'
today = datetime.date(2017, 10, 2)
while ans is 'Y' or ans is 'y':
d = input("Enter a date (DD/MM/YYYY)")
day = int(d[:2])
month = int(d[3:5])
year = int(d[6:])
thatday = datetime.date(year, month, day)
deltat = thatday - today
dif = int(deltat.days/7)
if dif is 6:
print("Sunday")
elif dif is 1:
print("Tuesday")
elif dif is 2:
print ("Wednesday")
elif dif is 3:
print("Thursday")
elif dif is 4:
print("Friday")
elif dif is 5:
print("Saturday")
else:
print("Monday")
ans = input("One more time, eh? (y/n)")
I started of trying to help you but got lost when I didn't really understood what you need.
Basically I think you need to read about strftime which prints a datetime object in a specific way: e.g. datetime.strftime("%A") gives weekday. You also need strptime which reads a date from a string, e.g. datetime.strptime("31/12/1999","%d/%m/%Y")
Look at your modified code below:
import datetime
ans = 'Y'
today = datetime.datetime.now().date()
while ans.title() == 'Y':
d = input("Enter a date (DD/MM/YYYY)")
thatday = datetime.datetime.strptime(d,"%d/%m/%Y").date()
deltat = thatday - today # timedelta
dif = int(deltat.days/7) # timedelta/7? What is this?
print(thatday.strftime("%A")) # Here you get the weekday of thatday
ans = input("One more time, eh? (y/n)")
if you're just looking for the day of the week you can also do this. The weekday() returns an integer value, with Monday being 0 and Sunday being 6
from datetime import *
weekdays = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
d = date(2017, 10, 2).weekday()
print(weekdays[d])
That date returns Monday

Making a time adding function in python

I'm trying to build a function that recieves a date and adds days, updating everything in case it changes, so far i've come up with this:
def addnewDate(date, numberOfDays):
date = date.split(":")
day = int(date[0])
month = int(date[1])
year = int(date[2])
new_days = 0
l = 0
l1 = 28
l2 = 30
l3 = 31
#l's are the accordingly days of the month
while numberOfDays > l:
numberOfDays = numberOfDays - l
if month != 12:
month += 1
else:
month = 1
year += 1
if month in [1, 3, 5, 7, 8, 10, 12]:
l = l3
elif month in [4, 6, 9, 11]:
l = l2
else:
l = l1
return str(day) + ':' + str(month) + ':' + str(year) #i'll deal
#with fact that it doesn't put the 0's in the < 10 digits later
Desired output:
addnewDate('29:12:2016', 5):
'03:01:2017'
I think the problem is with either the variables, or the position i'm using them in, kinda lost though..
Thanks in advance!
p.s I can't use python build in functions :)
Since you cannot use standard library, here's my attempt. I hope I did not forget anything.
define a table for month lengths
tweak it if leap year detected (every 4 year, but special cases)
work on zero-indexed days & months, much easier
add the number of days. If lesser that current month number of days, end, else, substract current month number of days and retry (while loop)
when last month reached, increase year
add 1 to day and month in the end
code:
def addnewDate(date, numberOfDays):
month_days = [31,28,31,30,31,30,31,31,30,31,30,31]
date = date.split(":")
day = int(date[0])-1
month = int(date[1])-1
year = int(date[2])
if year%4==0 and year%400!=0:
month_days[1]+=1
new_days = 0
#l's are the accordingly days of the month
day += numberOfDays
nb_days_month = month_days[month]
done = False # since you don't want to use break, let's create a flag
while not done:
nb_days_month = month_days[month]
if day < nb_days_month:
done = True
else:
day -= nb_days_month
month += 1
if month==12:
year += 1
month = 0
return "{:02}:{:02}:{:04}".format(day+1,month+1,year)
test (may be not exhaustive):
for i in ("28:02:2000","28:02:2004","28:02:2005","31:12:2012","03:02:2015"):
print(addnewDate(i,2))
print(addnewDate(i,31))
result:
02:03:2000
31:03:2000
01:03:2004
30:03:2004
02:03:2005
31:03:2005
02:01:2013
31:01:2013
05:02:2015
06:03:2015
of course, this is just for fun. Else use time or datetime modules!

Categories

Resources