¿Cómo puedo obtener el tercer viernes de un mes en Python?

Estoy tratando de obtener datos de stock de Yahoo! Financiar con Python 2.7.9, pero solo necesito datos para el tercer viernes del mes. Tengo una función para obtener los datos, pero necesito una forma de obtener las fechas. Quiero algo como esto:

def get_third_fris(how_many): # code and stuff return list_of_fris 

De modo que la llamada a get_third_fris(6) devolverá una lista de 6 artículos del 3er viernes posterior a la fecha actual. Las fechas deben ser las marcas de tiempo de Unix.

(No tengo mucha experiencia con el time o datetime , así que explique qué está haciendo su código).

¡Gracias!

Puedes usar el módulo de calendar para hacer una lista de semanas, luego tomar el viernes de esa semana.

 import calendar c = calendar.Calendar(firstweekday=calendar.SUNDAY) year = 2015; month = 2 monthcal = c.monthdatescalendar(year,month) third_friday = [day for week in monthcal for day in week if \ day.weekday() == calendar.FRIDAY and \ day.month == month][2] 

Puede dar formato a la marca de tiempo de Unix, pero no es trivial. Le referiré a esta excelente respuesta que contiene información basada en si su fecha es o no consciente de la zona horaria.

Puedes usar las funciones estándar de Python para encontrar el tercer viernes de este mes:

 from datetime import timedelta, date import calendar def next_third_friday(d): """ Given a third friday find next third friday""" d += timedelta(weeks=4) return d if d.day >= 15 else d + timedelta(weeks=1) def third_fridays(d, n): """Given a date, calculates n next third fridays""" # Find closest friday to 15th of month s = date(d.year, d.month, 15) result = [s + timedelta(days=(calendar.FRIDAY - s.weekday()) % 7)] # This month's third friday passed. Find next. if result[0] < d: result[0] = next_third_friday(result[0]) for i in range(n - 1): result.append(next_third_friday(result[-1])) return result 

Podemos aplicar la función anterior para obtener las marcas de tiempo de los próximos viernes:

 import time def timestamp(d): return int(time.mktime(d.timetuple())) fridays = third_fridays(date.today(), 2) print(fridays) print(map(timestamp, fridays)) 

Salida:

 [datetime.date(2015, 3, 20), datetime.date(2015, 4, 17)] [1426802400, 1429218000] 

¿Qué tal una respuesta más sencilla:

 import calendar c = calendar.Calendar(firstweekday=calendar.SATURDAY) monthcal = c.monthdatescalendar(my_year, my_month) monthly_expire_date = monthcal[2][-1] 

No necesitamos importar nada más que datetime. Podemos asumir 7 días a la semana y día de la semana 0 == lunes.

 import datetime def third_friday(year, month): """Return datetime.date for monthly option expiration given year and month """ # The 15th is the lowest third day in the month third = datetime.date(year, month, 15) # What day of the week is the 15th? w = third.weekday() # Friday is weekday 4 if w != 4: # Replace just the day (of month) third = third.replace(day=(15 + (4 - w) % 7)) return third 

Es fácil de usar dateutil para obtener el próximo viernes.

 import dateutil.parser as dparse from datetime import timedelta next_friday = dparse.parse("Friday") one_week = timedelta(days=7) friday_after_next = next_friday + one_week last_friday = friday_after_next + one_week 

esto aprovecha el hecho de que siempre hay una semana entre los viernes … aunque no estoy seguro de que esto responda a su pregunta, por lo menos debería brindarle un buen punto de partida.

Utilizando dateutil.relativedelta :

 from dateutil.relativedelta import relativedelta, FR # $ pip install python-dateutil def third_friday_dateutil(now): """the 3rd Friday of the month, not the 3rd Friday after today.""" now = now.replace(day=1) # 1st day of the month now += relativedelta(weeks=2, weekday=FR) return now 

O usando dateutil.rrule :

 from datetime import date, timedelta from dateutil.rrule import rrule, MONTHLY, FR def third_friday_rrule(now): return rrule(MONTHLY, count=1, byweekday=FR, bysetpos=3, dtstart=now.replace(day=1))[0] def get_third_fris_rrule(how_many): return list(rrule(MONTHLY, count=how_many, byweekday=FR, bysetpos=3, dtstart=date.today()+timedelta(1))) 

Aquí hay una solución de fuerza bruta (15 veces más rápido):

 #!/usr/bin/env python import calendar from datetime import date, timedelta from itertools import islice DAY = timedelta(1) WEEK = 7*DAY def fridays(now): while True: if now.weekday() == calendar.FRIDAY: while True: yield now now += WEEK now += DAY def next_month(now): """Return the first date that is in the next month.""" return (now.replace(day=15) + 20*DAY).replace(day=1) def third_friday_brute_force(now): """the 3rd Friday of the month, not the 3rd Friday after today.""" return next(islice(fridays(now.replace(day=1)), 2, 3)) def get_third_fris(how_many): result = [] now = date.today() while len(result) < how_many: fr = third_friday_brute_force(now) if fr > now: # use only the 3rd Friday after today result.append(fr) now = next_month(now) return result print(get_third_fris(6)) 

Salida

 [datetime.date(2015, 3, 20), datetime.date(2015, 4, 17), datetime.date(2015, 5, 15), datetime.date(2015, 6, 19), datetime.date(2015, 7, 17), datetime.date(2015, 8, 21)] 

Consulte Conversión de datetime.date en la marca de hora UTC en Python

Aquí está la comparación con otras soluciones y pruebas (para todos los patrones posibles de 400 años) .

Generalicé la respuesta de @pourhaus para encontrar el enésimo día de cualquier mes:

 def nth_day_of_month(month, year, day_of_week, n): first_possible_day = {1: 1, 2: 8, 3: 15, 4: 22, 5: 29}[n] d = datetime.date(year, month, first_possible_day) w = d.weekday() if w != day_of_week: d = d.replace(day=(first_possible_day + (day_of_week - w) % 7)) return d 
 from dateutil.relativedelta import * from datetime import * def find_mth_friday(your_date,m): mth_friday = your_date + relativedelta(day=1, weekday=FR(m)) #sets day=1 in your_date and adds m fridays to it. mth_friday_timestamp = int(mth_friday.strftime("%s")) #converting datetime to unix timestamp return mth_friday_timestamp def get_third_fris(n): output_timestamps = [] today = datetime.now() #gets current system date for i in range(1,n+1): #value of i varies from 1 to 6 if n=6 next_month = today + relativedelta(months=+i) #adds i months to current system date third_friday = find_mth_friday(next_month,3) #finds third friday of the month using 'find_mth_friday()', the function we defined output_timestamps.append(third_friday) return output_timestamps print(get_third_fris(6)) #let's try invoking our function with n=6 dates 

Esto es lo que querías ¿verdad?