views:

73

answers:

2

I am relatively new to Python, and I am experimenting with writing the following date calc functions

  • find the date that is/was Monday for a specified datetime
  • find the first non-weekend day of the month in a specified datetime
  • find the first non-weekend day of the year in a specified datetime
  • find the Nth [day of week] for a month in a specified datetime

Here are my attempts so far - if the logic can be improved (or corrected) to be more 'Pythonic', please let me know

import datetime

def find_month_first_monday(tstamp = datetime.today()):
    day_of_month = datetime.date.today().timetuple()[2]
    day_of_week = datetime.weekday(tstamp)
    # now I have the dow, and dom, I can index into a 2D array of
    # dates for the month - IF I knew how to get to that array ...


def find_first_gbd_in_month(tstamp = datetime.today()):
    # naive way would be to find the month and year from the passed in arg,
    # calculate the first day for that month/year and iterate until a non-weekend day
    # is found. Not elegant, there must be a better way
    pass


def find_first_gbd_in_year(tstamp = datetime.today()):
   # Ditto, as above.
    pass


def find_ndow_in_month(tstamp = datetime.today()):
    # again, I can get the month and the year from the passed in argument
    # what I need is a 2D array of dates for the month/year, so I can get
    # the nth dow (similar to reading off a calendar)
    pass
+3  A: 

find_month_first_monday

I'd use a different algorithm. First, find the first day of the month.

first_day_of_month = datetime.date.today().replace(day=1)

and find the week day of first_day_of_month,

week_day = first_day_of_month.weekday()

and add days if necessary.

if week_day:
  first_day_of_month += datetime.timedelta(days=7-week_day)

find_first_gbd_in_month

Similar to find_month_first_monday, but add the day only if week_day is 5 or 6 (Saturday and Sunday).

find_first_gbd_in_year

Supply the month=1 argument in .replace as well.

find_ndow_in_month

Find the first day of week, then add n-1 weeks.

KennyTM
@kenny: +1 for the nice and simple style - not sure I understand yur logic for the last function though - I suppose the name is a bit confusing. What that function does is return the Nth day of the week for a specified month - e.g. 2nd Wednesday of a month. Could you clarify if this indeed your understanding?
morpheous
@morpheous: Yes. In your case, first find the first Wednesday using the technique of `find_month_first_monday`, then do a `that_day += datetime.timedelta(weeks=2-1)`.
KennyTM
@kenny: thanks for the clarification
morpheous
+2  A: 

Use the excellent dateutil module. It is very easy to do that and other date calculations with it.

Some examples:

import datetime
from dateutil import rrule
today = datetime.date.today()

First friday of the month, for 10 months:

print list(rrule.rrule(rrule.MONTHLY, count=10, byweekday=rrule.MO(1),
    dtstart=today)))

results:

[datetime.datetime(2010, 8, 2, 0, 0),
 datetime.datetime(2010, 9, 6, 0, 0),
 datetime.datetime(2010, 10, 4, 0, 0),
 datetime.datetime(2010, 11, 1, 0, 0),
 datetime.datetime(2010, 12, 6, 0, 0),
 datetime.datetime(2011, 1, 3, 0, 0),
 datetime.datetime(2011, 2, 7, 0, 0),
 datetime.datetime(2011, 3, 7, 0, 0),
 datetime.datetime(2011, 4, 4, 0, 0),
 datetime.datetime(2011, 5, 2, 0, 0)]

First monday of the year, for 3 years:

print list(rrule.rrule(rrule.YEARLY, count=3, byweekday=rrule.MO(1),
    dtstart=datetime.date.today()))

Results:

[datetime.datetime(2011, 1, 3, 0, 0),
 datetime.datetime(2012, 1, 2, 0, 0),
 datetime.datetime(2013, 1, 7, 0, 0)]
nosklo