I want to print all Thursdays between these date ranges
from datetime import date, timedelta
sdate = date(2015, 1, 7) # start date
edate = date(2015, 12, 31) # end date
What is the best pythonic way to do that?
I want to print all Thursdays between these date ranges
from datetime import date, timedelta
sdate = date(2015, 1, 7) # start date
edate = date(2015, 12, 31) # end date
What is the best pythonic way to do that?
using your sdate.weekday() # returns int between 0 (mon) and 6 (sun)
:
sdate = ...
while sdate < edate:
if sdate.weekday() != 3: # not thursday
sdate += timedelta(days=1)
continue
# It is thursday
print(sdate)
sdate += timedelta(days=7) # next week
Compute the number of days till thursday from the start date :
days_to_thursday = (3 - sdate.weekday()) % 7
Compute the number of thursdays inbetween both dates:
week_diff = ((edate - sdate).days - days_to_thursday ) // 7
Get all thursdays in the date range:
thursdays = [sdate + timedelta(days=days_to_thursday + 7 * more_weeks) \
for more_weeks in range(week_diff + 1) ]
Print them if you need:
for t in thursdays:
print(t)
import datetime
import calendar
def weekday_count(start, end, day):
start_date = datetime.datetime.strptime(start, '%d/%m/%Y')
end_date = datetime.datetime.strptime(end, '%d/%m/%Y')
day_count = []
for i in range((end_date - start_date).days):
if calendar.day_name[(start_date + datetime.timedelta(days=i+1)).weekday()] == day:
print(str(start_date + datetime.timedelta(days=i+1)).split()[0])
weekday_count("01/01/2017", "31/01/2017", "Thursday")
# prints result
# 2017-01-05
# 2017-01-12
# 2017-01-19
# 2017-01-26
Simple solution:
from datetime import date, timedelta
sdate = date(2015, 1, 7) # start date
edate = date(2015, 12, 31) # end date
delta = edate - sdate
for day in range(delta.days + 1):
day_obj = sdate + timedelta(days=day)
if day_obj.weekday() == 3: # Thursday
print(day_obj)
# 2015-01-08
# 2015-01-15
# ...
# 2015-12-24
# 2015-12-31
The most efficient solution:
from datetime import date, timedelta
sdate = date(2015, 1, 7) # start date
edate = date(2015, 12, 31) # end date
day_index = 3 # Thursday
delta = (day_index - sdate.weekday()) % 7
match = sdate + timedelta(days=delta)
while match <= edate: # Change this to `<` to ignore the last one
print(match) # Can be easily converted to a generator with `yield`
match += timedelta(days=7)
# 2015-01-08
# 2015-01-15
# ...
# 2015-12-24
# 2015-12-31
Docs:
.weekday()
: https://docs.python.org/3/library/datetime.html#datetime.date.weekday.timedelta()
: https://docs.python.org/3/library/datetime.html#timedelta-objects%
operator on negative numbers: The modulo operation on negative numbers in PythonYou could try a list comprehension to get the Thursdays between the 2 dates.
This code actually outputs the dates as formatted strings but you can get actual dates by dropping the strftime
.
from datetime import date, timedelta
sdate = date(2015, 1, 7) # start date
edate = date(2015, 12, 31) # end date
thursdays = [(sdate+timedelta(days=d)).strftime('%A %Y-%m-%d') for d in range(0, (edate-sdate).days+1)
if (sdate+timedelta(days=d)).weekday() ==3]
print('\n'.join(thursdays))
""" Example output
Thursday 2015-01-08
Thursday 2015-01-15
Thursday 2015-01-22
Thursday 2015-01-29
Thursday 2015-02-05
Thursday 2015-02-12
""""
Most people are iterating through every day which is a waste. Also might be helpful to delay calculating the thursdays until you actually need them. For this you could use a generator.
def get_days(start, day_index, end=None):
# set the start as the next valid day
start += timedelta(days=(day_index - start.weekday()) % 7)
week = timedelta(days=7)
while end and start < end or not end:
yield start
start += week
This delays getting the next day until you need it, and allows infinite days if you don't specify and end date.
thursday_generator = get_days(date(2015, 1, 7), 3, date(2015, 12, 31))
print(list(thursday_generator))
"""
[datetime.date(2015, 1, 8), datetime.date(2015, 1, 15), datetime.date(2015, 1, 22), ...]
"""
You can easily dump as strings:
print("\n".join(map(str, thursday_generator)))
"""
2015-01-08
2015-01-15
2015-01-22
...
"""
You can also use f-strings for custom string formatting:
print("\n".join(f"{day:%A %x}" for day in thursday_generator))
"""
Thursday 01/08/15
Thursday 01/15/15
Thursday 01/22/15
...
"""
If you don't specify an end date, it goes on forever.
In [28]: thursday_generator = get_days(date(2015, 1, 7), 3)
...: print(len(list(thursday_generator)))
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
<ipython-input-28-b161cdcccc75> in <module>
1 thursday_generator = get_days(date(2015, 1, 7), 3)
----> 2 print(len(list(thursday_generator)))
<ipython-input-16-0691db329606> in get_days(start, day_index, end)
5 while end and start < end or not end:
6 yield start
----> 7 start += week
8
OverflowError: date value out of range