-
-
Save tporto/075713b7a4effd3af3b837c7db23fa4c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import re | |
import datetime | |
try: | |
import httplib # Python 2.7 | |
except ImportError: | |
import http.client as httplib # Python 3.x | |
def obter_feriados(cidade, uf, ano=None): | |
'''Obter lista de feriados por cidade e uf | |
de www.feriadosmunicipais.com.br para determinado ano.''' | |
# Conectar com o servidor www.feriadosmunicipais.com.br | |
conexao = httplib.HTTPConnection('www.feriadosmunicipais.com.br') | |
# Obter página dos feriados para a cidade e uf fornecidos | |
conexao.request('GET', '/{}/{}/'.format(uf, cidade)) | |
resposta = conexao.getresponse() | |
# Se teve algum erro, mostra o erro e retorna uma lista vazia | |
if resposta.status != 200: | |
conexao.close() | |
print("{} - {}".format(resposta.status, resposta.reason)) | |
return [] | |
# Ler o HTML | |
html = resposta.read() | |
conexao.close() | |
# Decodificar o HTML | |
charset = re.compile(b'.*charset="([^"]*)".*', re.DOTALL) | |
charset = re.sub(charset, r'\1', html) | |
html = html.decode(charset.decode()) | |
# Encontrar os feriados e carnaval onde o padrão é numa linha ter | |
# a data no formato dd/mm/aaaa e uma das palavras Feriado ou Carnaval | |
feriados = re.findall(r'([0-9]{2}/[0-9]{2}/[0-9]{4}).*' | |
r'(?:Feriado|Carnaval)', html) | |
# Converter para o tipo `datetime´ segundo padrão dd/mm/aaaa => %d/%m/%Y | |
feriados = [datetime.datetime.strptime(f, '%d/%m/%Y') for f in feriados] | |
# Filtrar as datas do ano desejado, se fornecido | |
if ano: | |
feriados = filter(lambda f: f.year == ano, feriados) | |
# Alterar o tipo de `datetime´ para `date´ | |
feriados = map(lambda f: datetime.date(f.year, f.month, f.day), feriados) | |
# Retornar os feriados ordenados | |
return sorted(feriados) | |
def converter_para_data(data): | |
'''Converte `data´ no padrão dd/mm/yyyy para o tipo datetime.date.''' | |
if not isinstance(data, (datetime.datetime, datetime.date)): | |
data = datetime.datetime.strptime(str(data), '%d/%m/%Y') | |
if isinstance(data, datetime.datetime): | |
data = datetime.date(data.year, data.month, data.day) | |
return data | |
def dia_util(data, feriados=[], sabado_util=False): | |
'''Retonar se o dia é útil (True) ou não (False) de acordo | |
com uma lista de feriados e se sábado será considerado útil.''' | |
data = converter_para_data(data) | |
semana = data.weekday() | |
return ((semana not in (5, 6) or (semana == 5 and sabado_util)) | |
and data not in feriados) | |
def proximo_dia_util(data, feriados=[], sabado_util=False, | |
anterior=False, d_mais=0): | |
'''Retonar o dia útil de acordo com uma lista de feriados e se | |
sábado será considerado útil, sendo a data fornecida | |
acrescida (anterior=False) ou decrescida (anterior=True) | |
de um dia útil mais `d_mais´ dias úteis. | |
Se `d_mais´ for negativo, retorna a data fornecida se esta for útil.''' | |
data = converter_para_data(data) | |
um_dia = datetime.timedelta(-1 if anterior else 1) | |
if d_mais > -1: | |
data += um_dia | |
while True: | |
while not dia_util(data, feriados, sabado_util): | |
data += um_dia | |
d_mais -= 1 | |
if d_mais < 0: | |
break | |
data = data + um_dia | |
return data | |
if __name__ == '__main__': | |
datas_teste = ['20/01/2017', '25/01/2017', '30/04/2017', '26/12/2017'] | |
print("\n\n*** Ribeirão Preto ***") | |
feriados = obter_feriados('ribeirao-preto', 'sao-paulo') | |
for feriado in feriados: | |
print(feriado.strftime("%d/%m/%Y")) | |
for data in datas_teste: | |
util = "é" if dia_util(data, feriados) else "não é" | |
print("{} {} dia útil nesta cidade!".format(data, util)) | |
proximo = proximo_dia_util(data, feriados) | |
print("\--> O próximo é {}".format(proximo.strftime("%d/%m/%Y"))) | |
anterior = proximo_dia_util(data, feriados, sabado_util=True, | |
anterior=True, d_mais=3) | |
print("\--> O anteior d+3 é {}".format(anterior.strftime("%d/%m/%Y"))) | |
print("\n\n*** São Paulo ***") | |
feriados = obter_feriados('sao-paulo', 'sao-paulo') | |
for feriado in feriados: | |
print(feriado.strftime("%d/%m/%Y")) | |
for data in datas_teste: | |
util = "é" if dia_util(data, feriados) else "não é" | |
print("{} {} dia útil nesta cidade!".format(data, util)) | |
proximo = proximo_dia_util(data, feriados) | |
print("\--> O próximo é {}".format(proximo.strftime("%d/%m/%Y"))) | |
anterior = proximo_dia_util(data, feriados, sabado_util=True, | |
anterior=True, d_mais=3) | |
print("\--> O anteior d+3 é {}".format(anterior.strftime("%d/%m/%Y"))) | |
# Caso de teste | |
data = '02/05/2017' | |
# Considerando retornar data se esta for útil (d_mais=-1) | |
anterior_util = proximo_dia_util(data, feriados, anterior=True, d_mais=-1) | |
anterior_util = anterior_util.strftime('%d/%m/%Y') | |
print("\n\n{} => este ou útil anterior é {}".format(data, anterior_util)) | |
# Não considerando retornar data se esta for útil (d_mais=0) | |
anterior_util = proximo_dia_util(data, feriados, anterior=True, d_mais=0) | |
anterior_util = anterior_util.strftime('%d/%m/%Y') | |
print("\n\n{} => dia útil anterior é {}".format(data, anterior_util)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment