How can I select all of the Sundays for a year using Python?
Asked Answered
H

10

52

Using Python...

How can I select all of the Sundays (or any day for that matter) in a year?

[ '01/03/2010','01/10/2010','01/17/2010','01/24/2010', ...]

These dates represent the Sundays for 2010. This could also apply to any day of the week I suppose.

Harquebusier answered 5/1, 2010 at 2:48 Comment(2)
Find the first Sunday and constantly add 7? Until you hit the limit of days for that month, then start from 0 ...Evacuate
See also very similar question from same person: #2004341Tombolo
A
75

You can use date from the datetime module to find the first Sunday in a year and then keep adding seven days, generating new Sundays:

from datetime import date, timedelta

def allsundays(year):
   d = date(year, 1, 1)                    # January 1st
   d += timedelta(days = 6 - d.weekday())  # First Sunday
   while d.year == year:
      yield d
      d += timedelta(days = 7)

for d in allsundays(2010):
   print(d)
Allopath answered 5/1, 2010 at 3:2 Comment(4)
Hey, I know its too late, but how to adjust the code for fetching saturdaysQuash
@sjpatel: You need to change the offset calculation to start with the first saturday instead of sunday. This could be done with timedelta(days = (5 - d.weekday() + 7) % 7). Or, more explicitly timedelta(days = (5 - d.weekday() if d.weekday() <= 5 else 7 + 5 - d.weekday()))Allopath
It will lost the day where sunday is 1st.Use "today + datetime.timedelta(days=-today.weekday(), weeks=1)" will better.Caplin
@Caplin pretty sure the original code works. January 1, 2012 is a Sunday. If you plug 2012 into the function it returns 2012-01-01 as the first entry.Bemoan
J
31

Pandas has great functionality for this purpose with its date_range() function.

The result is a pandas DatetimeIndex, but can be converted to a list easily.

import pandas as pd

def allsundays(year):
    return pd.date_range(start=str(year), end=str(year+1), 
                         freq='W-SUN').strftime('%m/%d/%Y').tolist()

allsundays(2017)[:5]  # First 5 Sundays of 2017
# ['01/01/2017', '01/08/2017', '01/15/2017', '01/22/2017', '01/29/2017']
Jarlathus answered 13/1, 2018 at 15:51 Comment(0)
C
15

Using the dateutil module, you could generate the list this way:

#!/usr/bin/env python
import dateutil.relativedelta as relativedelta
import dateutil.rrule as rrule
import datetime
year=2010
before=datetime.datetime(year,1,1)
after=datetime.datetime(year,12,31)
rr = rrule.rrule(rrule.WEEKLY,byweekday=relativedelta.SU,dtstart=before)
print rr.between(before,after,inc=True)

Although finding all Sundays is not too hard to do without dateutil, the module is handy especially if you have more complicated or varied date calculations.

If you are using Debian/Ubuntu, dateutil is provided by the python-dateutil package.

Chalkstone answered 5/1, 2010 at 3:24 Comment(1)
Shouldn't you replace before with after?Barefoot
B
10
from datetime import date, timedelta
from typing import List

def find_sundays_between(start: date, end: date) -> List[date]:
    total_days: int = (end - start).days + 1
    sunday: int = 6
    all_days = [start + timedelta(days=day) for day in range(total_days)]
    return [day for day in all_days if day.weekday() is sunday]


date_start: date = date(2018, 1, 1)
date_end: date = date(2018, 12, 31)
sundays = find_sundays_between(date_start, date_end)
Bourn answered 6/3, 2018 at 18:58 Comment(0)
H
7

If looking for a more general approach (ie not only Sundays), we can build on sth's answer:

def weeknum(dayname):
    if dayname == 'Monday':   return 0
    if dayname == 'Tuesday':  return 1
    if dayname == 'Wednesday':return 2
    if dayname == 'Thursday': return 3
    if dayname == 'Friday':   return 4
    if dayname == 'Saturday': return 5
    if dayname == 'Sunday':   return 6

This will translate the name of the day into an int.

Then do:

from datetime import date, timedelta
def alldays(year, whichDayYouWant):
    d = date(year, 1, 1)
    d += timedelta(days = (weeknum(whichDayYouWant) - d.weekday()) % 7)
    while d.year == year:
        yield d
        d += timedelta(days = 7)

for d in alldays(2020,'Sunday'):
    print(d)

Note the presence of % 7 in alldays(). This outputs:

2020-01-05
2020-01-12
2020-01-19
2020-01-26
2020-02-02
2020-02-09
2020-02-16
...

Can also do:

for d in alldays(2020,'Friday'):
    print(d)

which will give you:

2020-01-03
2020-01-10
2020-01-17
2020-01-24
2020-01-31
2020-02-07
2020-02-14
...
Headgear answered 21/8, 2020 at 12:7 Comment(0)
E
6

You can iterate over a calendar for that year. The below should return all Tuesdays and Thursdays for a given year.

# Returns all Tuesdays and Thursdays of a given year
from datetime import date
import calendar

year = 2016
c = calendar.TextCalendar(calendar.SUNDAY)
for m in range(1,13):
    for i in c.itermonthdays(year,m):
        if i != 0:                                      #calendar constructs months with leading zeros (days belongng to the previous month)
            day = date(year,m,i)
            if day.weekday() == 1 or day.weekday() == 3: #if its Tuesday or Thursday
                print "%s-%s-%s" % (year,m,i)
Ecg answered 14/11, 2016 at 3:14 Comment(1)
Nice answer! For strangers I want to notice, just add brackets to the print expression and this code will run by Python 3Inhabitancy
F
3
import time
from datetime import timedelta, datetime

first_date = '2021-01-01'
final_date = '2021-12-31'
first_date = datetime.strptime(first_date, '%Y-%m-%d')
last_date = datetime.strptime(final_date, '%Y-%m-%d')
week_day = 'Sunday'
dates = [first_date + timedelta(days=x) for x in range((last_date - first_date).days + 1) if (first_date + timedelta(days=x)).weekday() == time.strptime(week_day, '%A').tm_wday]

It will return all Sunday date of given date range.

Faruq answered 23/10, 2021 at 6:33 Comment(0)
C
1

Here's a complete generator function that builds on the solution from @sth. It includes the crucial fix that was mentioned in his solution's comments.

You can specify the day of week (using Python's indexing with 0=Monday to 6=Sunday), the starting date, and the number of weeks to enumerate.

def get_all_dates_of_day_of_week_in_year(day_of_week, start_year, start_month, 
                                         start_day, max_weeks=None):
    '''
    Generator function to enumerate all calendar dates for a specific day
    of the week during one year. For example, all Wednesdays in 2018 are:
    1/3/2018, 1/10/2018, 1/17/2018, 1/24/2018, 1/31/2018, 2/7/2018, etc.

    Parameters:
    ----------
    day_of_week : int
        The day_of_week should be one of these values: 0=Monday, 1=Tuesday, 
        2=Wednesday, 3=Thursday, 4=Friday, 5=Saturday, 6=Sunday.
    start_year : int
    start_month : int
    start_day : int
        The starting date from which to list out all the dates
    max_weeks : int or None
        If None, then list out all dates for the rest of the year.
        Otherwise, end the list after max_weeks number of weeks.
    '''

    if day_of_week < 0 or day_of_week > 6:
        raise ValueError('day_of_week should be in [0, 6]')

    date_iter = date(start_year, start_month, start_day)

    # First desired day_of_week
    date_iter += timedelta(days=(day_of_week - date_iter.weekday() + 7) % 7) 
    week = 1
    while date_iter.year == start_year:
        yield date_iter
        date_iter += timedelta(days=7)
        if max_weeks is not None:
            week += 1
            if week > max_weeks:
                break

Example usage to get all Wednesdays starting on January 1, 2018, for 10 weeks.

import calendar
day_of_week = 2
max_weeks = 10
for d in get_all_dates_of_day_of_week_in_year (day_of_week, 2018, 1, 1, max_weeks):
    print "%s, %d/%d/%d" % (calendar.day_name[d.weekday()], d.year, d.month, d.day)

The above code produces:

Wednesday, 2018/1/3
Wednesday, 2018/1/10
Wednesday, 2018/1/17
Wednesday, 2018/1/24
Wednesday, 2018/1/31
Wednesday, 2018/2/7
Wednesday, 2018/2/14
Wednesday, 2018/2/21
Wednesday, 2018/2/28
Wednesday, 2018/3/7
Cogswell answered 16/2, 2018 at 21:22 Comment(0)
U
1

according to @sth answer I like to give you an alternative without a function

from datetime import date, timedelta,datetime

sunndays = list()

year_var = datetime.now() #get current date
year_var = year_var.year  #get only the year

d = date(year_var, 1, 1)  #get the 01.01 of the current year = 01.01.2020

#now we have to skip 4 days to get to sunday.
#d.weekday is wednesday so it has a value of 2
d += timedelta(days=6 - d.weekday()) # 01.01.2020 + 4 days (6-2=4)

sunndays.append(str(d.strftime('%d-%m-%Y'))) #you need to catch the first sunday

#here you get every other sundays
while d.year == year_var:
    d += timedelta(days=7)
    sunndays.append(str(d.strftime('%d-%m-%Y')))

print(sunndays) # only for control

if you want every monday for example

#for 2021 the 01.01 is a friday the value is 4
#we need to skip 3 days 7-4 = 3
d += timedelta(days=7 - d.weekday())
Unexceptional answered 8/3, 2020 at 12:38 Comment(0)
C
0

according to @sth answer,it will lost the day when 1st is sunday.This will be better:

d = datetime.date(year, month-1, 28)
for _ in range(5):
    d = d + datetime.timedelta(days=-d.weekday(), weeks=1)
    if d.month!=month:
        break
    date.append(d)
Caplin answered 10/6, 2020 at 8:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.