10.1 Creating Calendars

Start by importing the calendar module. In this case import the whole module (all of its classes) instead of picking the ones we want to use.

import calendar
 
def main():
 
  # create a plain text calendar
  c = calendar.TextCalendar(calendar.SUNDAY)
  str = c.formatmonth(2017, 1, 0, 0)
  print str
 
  # create an HTML formatted calendar
  hc = calendar.HTMLCalendar(calendar.SUNDAY)
  str = hc.formatmonth(2017, 1)
  print str
 
if __name__ == "__main__":
  main()

The calendar.TextCalendar(calendar.SUNDAY) method takes an argument to set the first day of each week.

Calling the .formatmonth(2017, 1, 0, 0) method on the calendar allows you to pass in formatting options.

10.2 loop over the days of a month

import calendar
 
def main():
 
  c = calendar.TextCalendar(calendar.SUNDAY)
 
  # loop over the days of a month
  # zeroes mean that the day of the week is in an overlapping month
  for i in c.itermonthdays(2013, 8):
    print i
 
if __name__ == "__main__":
  main()

The .itermonthdays(2013, 8) method is a function that allow iterating through the days of a month in a for loop. It takes the year and the month you want to operateon as arguments.

In the output zeroes mean that the day of the week is in an overlapping month.

10.3 Calendar locale

import calendar
 
def main():
 
  # The Calendar module provides useful utilities for the given locale,
  # such as the names of days and months in both full and abbreviated forms
  for name in calendar.month_name:
    print name
 
  for day in calendar.day_name:
    print day
 
if __name__ == "__main__":
  main()

If the locale was set to China (for instance) the day and month names would be output in the appropriate format

10.4 Calculate days based on a rule

For example, consider a team meeting on the first Friday of every month. To figure out what days that would be for each month, we can use this script:

import calendar
 
def main():
 
  for m in range(1,13):
    # returns an array of weeks that represent the month
    cal = calendar.monthcalendar(2017, m)
    # The first Friday has to be within the first two weeks
    weekone = cal[0]
    weektwo = cal[1]
 
    if weekone[calendar.FRIDAY] != 0: # zeros belong to another month
      meetday = weekone[calendar.FRIDAY]
    else:
      # if the first friday isn't in the first week, it must be in the second
      meetday = weektwo[calendar.FRIDAY]
 
    print "%10s %2d" % (calendar.month_name[m], meetday)
 
if __name__ == "__main__":
  main()

Calendar's .monthcalendar(2017, m) method returns an array of weeks for a given month. We call it for each month in our array of months (m)

This results in a list of arrays (one for each month,) inside of which is an array of weeks, which contain the dates: [[0, 0, 0, 0, 0, 0, 1], [2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22], [23, 24, 25, 26, 27, 28, 29], [30, 31, 0, 0, 0, 0, 0]]

Looking at the above array… and the condition:

if weekone[calendar.FRIDAY] != 0: # zeros belong to another month
  meetday = weekone[calendar.FRIDAY]

In week one [0, 0, 0, 0, 0, 0, 1] where the first position is MONDAY (because that is the default calendar output and we haven't specified another day to start a week,) we can see that the first day of the month is a SUNDAY, so this first condition isn't met.

For the second condition, looking at the second week in the about array:

else:
  # if the first friday isn't in the first week, it must be in the second
  meetday = weektwo[calendar.FRIDAY]

The first FRIDAY of the month occurs on the sixth day of the month [2, 3, 4, 5, 6, 7, 8]

Now looping through each month (each value in our variable m ) gives us:

   January  6
  February  3
     March  3
     April  7
       May  5
      June  2
      July  7
    August  4
 September  1
   October  6
  November  3
  December  1

Super cool.

N.B. The FRIDAY in calendar.FRIDAY is a constant within the calendars module.

Lastly in this print statement: print "%10s %2d" % (calendar.month_name[m], meetday), this "%10s %2d" is a formatting string.

The print method is taking in two arguments and the first formatting string applies to the first and second formatting string applies to the second, so...

%10s says pad the output string s with 10 spaces and %2d says pad the integer d with two spaces.