30 банковских дней

Делал жене программу, чтобы отсчитывать от введёной даты 30 банковских дней в текущем году, может пригодится кому (в запускаемый файл преобразовал при помощи PyInstaller, получается один файл, очень удобно). При первом запуске программа скачивает календарь с сайта Calend.Ru и сохраняет рядом, потом берёт из него выходные и праздничные дни.

# coding: utf-8
import re
import httplib
import pickle
import ctypes
from datetime import date, datetime, timedelta

MB_OKCANCEL = 1
MB_SYSTEMMODAL = 4096
IDOK = 1
IDCANCEL = 2

def getCalend():
    h = httplib.HTTPConnection('www.calend.ru')
    h.request('GET', '/work/')
    return h.getresponse().read()

def getHolidays():
    table = re.findall(r'<table\s.+?time_of_death(.+)</table>', getCalend(), re.DOTALL)[0]
    return re.findall(r'<td\s+class="\S+\s+col5"\s+day="(\d+)"\s+month="(\d+)"', table, re.DOTALL)

def readHolidays():
    year = str(date.today().year)
    try:
        with open(year + '.cache', 'r') as f:
            holidays = pickle.load(f)
    except IOError:
        with open(year + '.cache', 'w') as f:
            holidays = tuple(getHolidays())
            pickle.dump(holidays, f)

    return [datetime(day=int(d[0]), month=int(d[1]), year=int(year)) for d in holidays]

def getStartDate():
    while 1:
        input = re.split(r'\D', raw_input("Enter start date (dd.mm): "))
        try:
            input = [int(x) for x in input]
            if len(input) == 2:
                break
        except ValueError:
            pass

    return (date.today().year, input[1], input[0])

delta = timedelta(days = 1)

holidays = readHolidays()
msgbox = ctypes.windll.user32.MessageBoxW

while 1:
    try:
        date = datetime(*getStartDate())

        for i in xrange(0, 30):
            while 1:
                date += delta

                if date not in holidays: break

    if msgbox(
            0,
            u'Получилась следующая дата: %02d.%02d.%04d' % (date.day, date.month, date.year),
            u'Ответ',
            MB_OKCANCEL | MB_SYSTEMMODAL
        ) == IDCANCEL:
        raise StopIteration
    except (KeyboardInterrupt, StopIteration):
        break

Программу написал быстро, а сложнее всего было её отправить — ГМэйл упорно не принимает запускаемые файлы, даже в архивах.

Комментарии 15

Михаил Калашник (splurov.livejournal.com) № 3
А вы с женой дропбоксом с зашареной папкой не пользуетесь? Очень удобно :)
Евгений Степанищев (bolknote.ru) автор № 5
А вы с женой дропбоксом с зашареной папкой не пользуетесь? Очень удобно :)

Да кто ей на работе позволит дропбокс подключить к рабочему компу?

hshhhhh (hshhhhh.name) № 8

Комментарий для Евгения Степанищева:

Т.е. дропбокс нельзя, а гит ставить можно? :)

Ну с гитхаба можно было и просто так скачать через браузер :)

Евгений Степанищев (bolknote.ru) автор № 9
У неё там странно всё, никогда не знаешь какой ресурс доступен, а почта точно доступна :)
nazikus № 10

Комментарий для Евгения Степанищева:

а сложнее всего было её отправить — ГМэйл упорно не принимает запускаемые файлы, даже в архивах.

Поменяйте расширение на .txt

Евгений Степанищев (bolknote.ru) автор № 11
Я уже плохо помню Винду, но, кажется, она сопротивляется теперь, когда пытаешься файл в exe переименовать. Может, путаю, конечно.
vladon (vladon.ru) № 14
Я отправлю гуглом в 7z.

А как решил вопрос с татарстанскими праздниками? Которые в РТ не банковские дни, а в РФ — банковские?