4

I need to get the 2nd Friday of each month in Python.

I have written the function below that demonstrates what I need. However, I am wondering if there is a more elegant way to do it using Pandas' date_range function and appropriate offsets.

def second_friday_of_month_date_range( start, end ):
    dr = pd.date_range( start, end, freq='MS' )

    first_weekday_of_month_to_2nd_friday_of_month = np.array( [ 12, 11, 10, 9, 8, 14, 13 ], dtype=int )
    wd                                            = first_weekday_of_month_to_2nd_friday_of_month[ dr.weekday ]
    offsets                                       = [ datetime.timedelta( days=int(x)-1 ) for x in wd ]
    dts                                           = [d+o for d, o in zip( dr, offsets)]
    return pd.DatetimeIndex( dts )

import pandas as pd
import datetime
d0 = datetime.datetime(2016,1,1)
d1 = datetime.datetime(2017,1,1)
dr = second_friday_of_month_date_range( d0, d1 )
print( dr )

>> DatetimeIndex(['2016-01-08', '2016-02-12', '2016-03-11', '2016-04-08',
               '2016-05-13', '2016-06-10', '2016-07-08', '2016-08-12',
               '2016-09-09', '2016-10-14', '2016-11-11', '2016-12-09',
               '2017-01-13'],
              dtype='datetime64[ns]', freq=None, tz=None)
Alex Riley
  • 169,130
  • 45
  • 262
  • 238
Ginger
  • 8,320
  • 12
  • 56
  • 99

2 Answers2

5

You can do this easily by setting freq='WOM-2FRI' ("week of month, second Friday") in pd.date_range. So to get your expected output, you could write:

pd.date_range('2016-01-01', freq='WOM-2FRI', periods=13)

The output is:

DatetimeIndex(['2016-01-08', '2016-02-12', '2016-03-11', '2016-04-08',
               '2016-05-13', '2016-06-10', '2016-07-08', '2016-08-12',
               '2016-09-09', '2016-10-14', '2016-11-11', '2016-12-09',
               '2017-01-13'],
              dtype='datetime64[ns]', freq='WOM-2FRI')
Alex Riley
  • 169,130
  • 45
  • 262
  • 238
  • 1
    can you share a link to the _secret_ place where it's documented? Currently I must _parse_ pandas source files in order to find some information about `frequency` rules – MaxU - stand with Ukraine Apr 17 '16 at 10:35
  • 1
    @MaxU: I think [DateOffset objects](http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects) is the main place where this type of functionality is documented, although that page doesn't cover setting parameters such as `freq='WOM-3TUE'` directly. I inferred the string pattern from playing about with `pd.offsets.WeekOfMonth`. – Alex Riley Apr 17 '16 at 10:45
  • 1
    Thank you! It's a pity that such a rich pandas functionality documented that poorly :( – MaxU - stand with Ukraine Apr 17 '16 at 10:50
  • 1
    I've also found some _interesting_ stuff here: `pandas/tseries/tests/test_frequencies.py` – MaxU - stand with Ukraine Apr 17 '16 at 11:03
2

try this aproach:

import dateutil as du
import pandas as pd

start=du.parser.parse('2016-01-01')

rr = du.rrule.rrule(du.rrule.MONTHLY,
                    byweekday=du.relativedelta.FR(2),
                    dtstart=start,
                    count=12)

dates = [pd.to_datetime(d) for d in rr]

Output:

In [33]: dates
Out[33]:
[Timestamp('2016-01-08 00:00:00'),
 Timestamp('2016-02-12 00:00:00'),
 Timestamp('2016-03-11 00:00:00'),
 Timestamp('2016-04-08 00:00:00'),
 Timestamp('2016-05-13 00:00:00'),
 Timestamp('2016-06-10 00:00:00'),
 Timestamp('2016-07-08 00:00:00'),
 Timestamp('2016-08-12 00:00:00'),
 Timestamp('2016-09-09 00:00:00'),
 Timestamp('2016-10-14 00:00:00'),
 Timestamp('2016-11-11 00:00:00'),
 Timestamp('2016-12-09 00:00:00')]
Community
  • 1
  • 1
MaxU - stand with Ukraine
  • 205,989
  • 36
  • 386
  • 419